Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:29:26

0001 //
0002 // Copyright (c) 2015-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
0003 //
0004 // Distributed under the Boost Software License, Version 1.0. (See accompanying
0005 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
0006 //
0007 // Official repository: https://github.com/boostorg/beast
0008 //
0009 
0010 #ifndef BOOST_BEAST_CORE_IMPL_FILE_STDIO_IPP
0011 #define BOOST_BEAST_CORE_IMPL_FILE_STDIO_IPP
0012 
0013 #include <boost/beast/core/file_stdio.hpp>
0014 #include <boost/beast/core/detail/win32_unicode_path.hpp>
0015 #include <boost/config/workaround.hpp>
0016 #include <boost/core/exchange.hpp>
0017 #include <limits>
0018 
0019 namespace boost {
0020 namespace beast {
0021 
0022 file_stdio::
0023 ~file_stdio()
0024 {
0025     if(f_)
0026         fclose(f_);
0027 }
0028 
0029 file_stdio::
0030 file_stdio(file_stdio&& other)
0031     : f_(boost::exchange(other.f_, nullptr))
0032 {
0033 }
0034 
0035 file_stdio&
0036 file_stdio::
0037 operator=(file_stdio&& other)
0038 {
0039     if(&other == this)
0040         return *this;
0041     if(f_)
0042         fclose(f_);
0043     f_ = other.f_;
0044     other.f_ = nullptr;
0045     return *this;
0046 }
0047 
0048 void
0049 file_stdio::
0050 native_handle(std::FILE* f)
0051 {
0052     if(f_)
0053         fclose(f_);
0054     f_ = f;
0055 }
0056 
0057 void
0058 file_stdio::
0059 close(error_code& ec)
0060 {
0061     if(f_)
0062     {
0063         int failed = fclose(f_);
0064         f_ = nullptr;
0065         if(failed)
0066         {
0067             ec.assign(errno, generic_category());
0068             return;
0069         }
0070     }
0071     ec = {};
0072 }
0073 
0074 void
0075 file_stdio::
0076 open(char const* path, file_mode mode, error_code& ec)
0077 {
0078     if(f_)
0079     {
0080         fclose(f_);
0081         f_ = nullptr;
0082     }
0083     ec = {};
0084 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0085     boost::winapi::WCHAR_ const* s;
0086     detail::win32_unicode_path unicode_path(path, ec);
0087     if (ec)
0088         return;
0089 #else
0090     char const* s;
0091 #endif
0092     switch(mode)
0093     {
0094     default:
0095     case file_mode::read:
0096     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0097         s = L"rb";
0098     #else
0099         s = "rb";
0100     #endif
0101         break;
0102 
0103     case file_mode::scan:
0104     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0105         s = L"rbS";
0106     #else
0107         s = "rb";
0108     #endif
0109         break;
0110 
0111     case file_mode::write:
0112     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0113         s = L"wb+";
0114     #else
0115         s = "wb+";
0116     #endif
0117         break;
0118 
0119     case file_mode::write_new:
0120     {
0121 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0122 # if (defined(BOOST_MSVC) && BOOST_MSVC >= 1910) || (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION >= 141)
0123         s = L"wbx";
0124 # else
0125         std::FILE* f0;
0126         auto const ev = ::_wfopen_s(&f0, unicode_path.c_str(), L"rb");
0127         if(! ev)
0128         {
0129             std::fclose(f0);
0130             ec = make_error_code(errc::file_exists);
0131             return;
0132         }
0133         else if(ev !=
0134             errc::no_such_file_or_directory)
0135         {
0136             ec.assign(ev, generic_category());
0137             return;
0138         }
0139         s = L"wb";
0140 # endif
0141 #else
0142         s = "wbx";
0143 #endif
0144         break;
0145     }
0146 
0147     case file_mode::write_existing:
0148     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0149         s = L"rb+";
0150     #else
0151         s = "rb+";
0152     #endif
0153         break;
0154 
0155     case file_mode::append:
0156     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0157         s = L"ab";
0158     #else
0159         s = "ab";
0160     #endif
0161         break;
0162 
0163     case file_mode::append_existing:
0164     {
0165 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0166         std::FILE* f0;
0167         auto const ev =
0168             ::_wfopen_s(&f0, unicode_path.c_str(), L"rb+");
0169         if(ev)
0170         {
0171             ec.assign(ev, generic_category());
0172             return;
0173         }
0174 #else
0175         auto const f0 =
0176             std::fopen(path, "rb+");
0177         if(! f0)
0178         {
0179             ec.assign(errno, generic_category());
0180             return;
0181         }
0182 #endif
0183         std::fclose(f0);
0184     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0185         s = L"ab";
0186     #else
0187         s = "ab";
0188     #endif
0189         break;
0190     }
0191     }
0192 
0193 #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
0194     auto const ev = ::_wfopen_s(&f_, unicode_path.c_str(), s);
0195     if(ev)
0196     {
0197         f_ = nullptr;
0198         ec.assign(ev, generic_category());
0199         return;
0200     }
0201 #else
0202     f_ = std::fopen(path, s);
0203     if(! f_)
0204     {
0205         ec.assign(errno, generic_category());
0206         return;
0207     }
0208 #endif
0209 }
0210 
0211 std::uint64_t
0212 file_stdio::
0213 size(error_code& ec) const
0214 {
0215     if(! f_)
0216     {
0217         ec = make_error_code(errc::bad_file_descriptor);
0218         return 0;
0219     }
0220     long pos = std::ftell(f_);
0221     if(pos == -1L)
0222     {
0223         ec.assign(errno, generic_category());
0224         return 0;
0225     }
0226     int result = std::fseek(f_, 0, SEEK_END);
0227     if(result != 0)
0228     {
0229         ec.assign(errno, generic_category());
0230         return 0;
0231     }
0232     long size = std::ftell(f_);
0233     if(size == -1L)
0234     {
0235         ec.assign(errno, generic_category());
0236         std::fseek(f_, pos, SEEK_SET);
0237         return 0;
0238     }
0239     result = std::fseek(f_, pos, SEEK_SET);
0240     if(result != 0)
0241         ec.assign(errno, generic_category());
0242     else
0243         ec = {};
0244     return size;
0245 }
0246 
0247 std::uint64_t
0248 file_stdio::
0249 pos(error_code& ec) const
0250 {
0251     if(! f_)
0252     {
0253         ec = make_error_code(errc::bad_file_descriptor);
0254         return 0;
0255     }
0256     long pos = std::ftell(f_);
0257     if(pos == -1L)
0258     {
0259         ec.assign(errno, generic_category());
0260         return 0;
0261     }
0262     ec = {};
0263     return pos;
0264 }
0265 
0266 void
0267 file_stdio::
0268 seek(std::uint64_t offset, error_code& ec)
0269 {
0270     if(! f_)
0271     {
0272         ec = make_error_code(errc::bad_file_descriptor);
0273         return;
0274     }
0275     if(offset > static_cast<std::uint64_t>((std::numeric_limits<long>::max)()))
0276     {
0277         ec = make_error_code(errc::invalid_seek);
0278         return;
0279     }
0280     int result = std::fseek(f_,
0281         static_cast<long>(offset), SEEK_SET);
0282     if(result != 0)
0283         ec.assign(errno, generic_category());
0284     else
0285         ec = {};
0286 }
0287 
0288 std::size_t
0289 file_stdio::
0290 read(void* buffer, std::size_t n, error_code& ec) const
0291 {
0292     if(! f_)
0293     {
0294         ec = make_error_code(errc::bad_file_descriptor);
0295         return 0;
0296     }
0297     auto nread = std::fread(buffer, 1, n, f_);
0298     if(std::ferror(f_))
0299     {
0300         ec.assign(errno, generic_category());
0301         return 0;
0302     }
0303     return nread;
0304 }
0305 
0306 std::size_t
0307 file_stdio::
0308 write(void const* buffer, std::size_t n, error_code& ec)
0309 {
0310     if(! f_)
0311     {
0312         ec = make_error_code(errc::bad_file_descriptor);
0313         return 0;
0314     }
0315     auto nwritten = std::fwrite(buffer, 1, n, f_);
0316     if(std::ferror(f_))
0317     {
0318         ec.assign(errno, generic_category());
0319         return 0;
0320     }
0321     return nwritten;
0322 }
0323 
0324 } // beast
0325 } // boost
0326 
0327 #endif