LCOV - code coverage report
Current view: top level - http_proto/impl - file_stdio.ipp (source / functions) Hit Total Coverage
Test: coverage_filtered.info Lines: 108 127 85.0 %
Date: 2023-02-02 18:17:21 Functions: 11 11 100.0 %

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2022 Vinnie Falco (vinnie dot falco at gmail dot com)
       3             : //
       4             : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5             : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6             : //
       7             : // Official repository: https://github.com/CPPAlliance/http_proto
       8             : //
       9             : 
      10             : #ifndef BOOST_HTTP_PROTO_IMPL_FILE_STDIO_IPP
      11             : #define BOOST_HTTP_PROTO_IMPL_FILE_STDIO_IPP
      12             : 
      13             : #include <boost/http_proto/file_stdio.hpp>
      14             : #include <boost/http_proto/error.hpp>
      15             : #include <boost/http_proto/detail/win32_unicode_path.hpp>
      16             : #include <boost/config/workaround.hpp>
      17             : #include <boost/core/exchange.hpp>
      18             : #include <limits>
      19             : 
      20             : namespace boost {
      21             : namespace http_proto {
      22             : 
      23          23 : file_stdio::
      24          23 : ~file_stdio()
      25             : {
      26          23 :     if(f_)
      27          11 :         fclose(f_);
      28          23 : }
      29             : 
      30           1 : file_stdio::
      31             : file_stdio(
      32           1 :     file_stdio&& other) noexcept
      33           1 :     : f_(boost::exchange(other.f_, nullptr))
      34             : {
      35           1 : }
      36             : 
      37             : file_stdio&
      38           3 : file_stdio::
      39             : operator=(
      40             :     file_stdio&& other) noexcept
      41             : {
      42           3 :     if(&other == this)
      43           1 :         return *this;
      44           2 :     if(f_)
      45           1 :         fclose(f_);
      46           2 :     f_ = other.f_;
      47           2 :     other.f_ = nullptr;
      48           2 :     return *this;
      49             : }
      50             : 
      51             : void
      52           1 : file_stdio::
      53             : native_handle(std::FILE* f)
      54             : {
      55           1 :     if(f_)
      56           1 :         fclose(f_);
      57           1 :     f_ = f;
      58           1 : }
      59             : 
      60             : void
      61           4 : file_stdio::
      62             : close(error_code& ec)
      63             : {
      64           4 :     if(f_)
      65             :     {
      66           4 :         int failed = fclose(f_);
      67           4 :         f_ = nullptr;
      68           4 :         if(failed)
      69             :         {
      70           0 :             ec.assign(errno, generic_category());
      71           0 :             return;
      72             :         }
      73             :     }
      74           4 :     ec = {};
      75             : }
      76             : 
      77             : void
      78          21 : file_stdio::
      79             : open(char const* path, file_mode mode, error_code& ec)
      80             : {
      81          21 :     if(f_)
      82             :     {
      83           1 :         fclose(f_);
      84           1 :         f_ = nullptr;
      85             :     }
      86          21 :     ec = {};
      87             : #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
      88             :     boost::winapi::WCHAR_ const* s;
      89             :     detail::win32_unicode_path unicode_path(path, ec);
      90             :     if (ec)
      91             :         return;
      92             : #else
      93             :     char const* s;
      94             : #endif
      95          21 :     switch(mode)
      96             :     {
      97           2 :     default:
      98             :     case file_mode::read:
      99             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     100             :         s = L"rb";
     101             :     #else
     102           2 :         s = "rb";
     103             :     #endif
     104           2 :         break;
     105             : 
     106           1 :     case file_mode::scan:
     107             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     108             :         s = L"rbS";
     109             :     #else
     110           1 :         s = "rb";
     111             :     #endif
     112           1 :         break;
     113             : 
     114          10 :     case file_mode::write:
     115             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     116             :         s = L"wb+";
     117             :     #else
     118          10 :         s = "wb+";
     119             :     #endif
     120          10 :         break;
     121             : 
     122           2 :     case file_mode::write_new:
     123             :     {
     124             : #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     125             : # if (defined(BOOST_MSVC) && BOOST_MSVC >= 1910) || (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION >= 141)
     126             :         s = L"wbx";
     127             : # else
     128             :         std::FILE* f0;
     129             :         auto const ev = ::_wfopen_s(&f0, unicode_path.c_str(), L"rb");
     130             :         if(! ev)
     131             :         {
     132             :             std::fclose(f0);
     133             :             ec = make_error_code(errc::file_exists);
     134             :             return;
     135             :         }
     136             :         else if(ev !=
     137             :             errc::no_such_file_or_directory)
     138             :         {
     139             :             ec.assign(ev, generic_category());
     140             :             return;
     141             :         }
     142             :         s = L"wb";
     143             : # endif
     144             : #else
     145           2 :         s = "wbx";
     146             : #endif
     147           2 :         break;
     148             :     }
     149             : 
     150           2 :     case file_mode::write_existing:
     151             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     152             :         s = L"rb+";
     153             :     #else
     154           2 :         s = "rb+";
     155             :     #endif
     156           2 :         break;
     157             : 
     158           2 :     case file_mode::append:
     159             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     160             :         s = L"ab";
     161             :     #else
     162           2 :         s = "ab";
     163             :     #endif
     164           2 :         break;
     165             : 
     166           2 :     case file_mode::append_existing:
     167             :     {
     168             : #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     169             :         std::FILE* f0;
     170             :         auto const ev =
     171             :             ::_wfopen_s(&f0, unicode_path.c_str(), L"rb+");
     172             :         if(ev)
     173             :         {
     174             :             ec.assign(ev, generic_category());
     175             :             return;
     176             :         }
     177             : #else
     178             :         auto const f0 =
     179           2 :             std::fopen(path, "rb+");
     180           2 :         if(! f0)
     181             :         {
     182           1 :             ec.assign(errno, generic_category());
     183           1 :             return;
     184             :         }
     185             : #endif
     186           1 :         std::fclose(f0);
     187             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     188             :         s = L"ab";
     189             :     #else
     190           1 :         s = "ab";
     191             :     #endif
     192           1 :         break;
     193             :     }
     194             :     }
     195             : 
     196             : #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     197             :     auto const ev = ::_wfopen_s(&f_, unicode_path.c_str(), s);
     198             :     if(ev)
     199             :     {
     200             :         f_ = nullptr;
     201             :         ec.assign(ev, generic_category());
     202             :         return;
     203             :     }
     204             : #else
     205          20 :     f_ = std::fopen(path, s);
     206          20 :     if(! f_)
     207             :     {
     208           2 :         ec.assign(errno, generic_category());
     209           2 :         return;
     210             :     }
     211             : #endif
     212             : }
     213             : 
     214             : std::uint64_t
     215           2 : file_stdio::
     216             : size(error_code& ec) const
     217             : {
     218           2 :     if(! f_)
     219             :     {
     220           1 :         ec = make_error_code(errc::bad_file_descriptor);
     221           1 :         return 0;
     222             :     }
     223           1 :     long pos = std::ftell(f_);
     224           1 :     if(pos == -1L)
     225             :     {
     226           0 :         ec.assign(errno, generic_category());
     227           0 :         return 0;
     228             :     }
     229           1 :     int result = std::fseek(f_, 0, SEEK_END);
     230           1 :     if(result != 0)
     231             :     {
     232           0 :         ec.assign(errno, generic_category());
     233           0 :         return 0;
     234             :     }
     235           1 :     long size = std::ftell(f_);
     236           1 :     if(size == -1L)
     237             :     {
     238           0 :         ec.assign(errno, generic_category());
     239           0 :         std::fseek(f_, pos, SEEK_SET);
     240           0 :         return 0;
     241             :     }
     242           1 :     result = std::fseek(f_, pos, SEEK_SET);
     243           1 :     if(result != 0)
     244           0 :         ec.assign(errno, generic_category());
     245             :     else
     246           1 :         ec = {};
     247           1 :     return size;
     248             : }
     249             : 
     250             : std::uint64_t
     251           3 : file_stdio::
     252             : pos(error_code& ec) const
     253             : {
     254           3 :     if(! f_)
     255             :     {
     256           1 :         ec = make_error_code(errc::bad_file_descriptor);
     257           1 :         return 0;
     258             :     }
     259           2 :     long pos = std::ftell(f_);
     260           2 :     if(pos == -1L)
     261             :     {
     262           0 :         ec.assign(errno, generic_category());
     263           0 :         return 0;
     264             :     }
     265           2 :     ec = {};
     266           2 :     return pos;
     267             : }
     268             : 
     269             : void
     270           2 : file_stdio::
     271             : seek(std::uint64_t offset, error_code& ec)
     272             : {
     273           2 :     if(! f_)
     274             :     {
     275           1 :         ec = make_error_code(errc::bad_file_descriptor);
     276           1 :         return;
     277             :     }
     278           1 :     if(offset > static_cast<std::uint64_t>((std::numeric_limits<long>::max)()))
     279             :     {
     280           0 :         ec = make_error_code(errc::invalid_seek);
     281           0 :         return;
     282             :     }
     283           1 :     int result = std::fseek(f_,
     284             :         static_cast<long>(offset), SEEK_SET);
     285           1 :     if(result != 0)
     286           0 :         ec.assign(errno, generic_category());
     287             :     else
     288           1 :         ec = {};
     289             : }
     290             : 
     291             : std::size_t
     292           3 : file_stdio::
     293             : read(void* buffer, std::size_t n, error_code& ec) const
     294             : {
     295           3 :     if(! f_)
     296             :     {
     297           1 :         ec = make_error_code(errc::bad_file_descriptor);
     298           1 :         return 0;
     299             :     }
     300           2 :     auto nread = std::fread(buffer, 1, n, f_);
     301           2 :     if(std::ferror(f_))
     302             :     {
     303           0 :         ec.assign(errno, generic_category());
     304           0 :         return 0;
     305             :     }
     306           2 :     return nread;
     307             : }
     308             : 
     309             : std::size_t
     310           5 : file_stdio::
     311             : write(void const* buffer, std::size_t n, error_code& ec)
     312             : {
     313           5 :     if(! f_)
     314             :     {
     315           1 :         ec = make_error_code(errc::bad_file_descriptor);
     316           1 :         return 0;
     317             :     }
     318           4 :     auto nwritten = std::fwrite(buffer, 1, n, f_);
     319           4 :     if(std::ferror(f_))
     320             :     {
     321           0 :         ec.assign(errno, generic_category());
     322           0 :         return 0;
     323             :     }
     324           4 :     return nwritten;
     325             : }
     326             : 
     327             : } // http_proto
     328             : } // boost
     329             : 
     330             : #endif

Generated by: LCOV version 1.15