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-03-01 04:29:22 Functions: 11 11 100.0 %

          Line data    Source code
       1             : //
       2             : // Copyright (c) 2022 Vinnie Falco (vinnie.falco@gmail.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(
      63             :     system::error_code& ec)
      64             : {
      65           4 :     if(f_)
      66             :     {
      67           4 :         int failed = fclose(f_);
      68           4 :         f_ = nullptr;
      69           4 :         if(failed)
      70             :         {
      71           0 :             ec.assign(errno,
      72             :                 system::generic_category());
      73           0 :             return;
      74             :         }
      75             :     }
      76           4 :     ec = {};
      77             : }
      78             : 
      79             : void
      80          21 : file_stdio::
      81             : open(char const* path, file_mode mode,
      82             :     system::error_code& ec)
      83             : {
      84          21 :     if(f_)
      85             :     {
      86           1 :         fclose(f_);
      87           1 :         f_ = nullptr;
      88             :     }
      89          21 :     ec = {};
      90             : #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
      91             :     boost::winapi::WCHAR_ const* s;
      92             :     detail::win32_unicode_path unicode_path(path, ec);
      93             :     if (ec)
      94             :         return;
      95             : #else
      96             :     char const* s;
      97             : #endif
      98          21 :     switch(mode)
      99             :     {
     100           2 :     default:
     101             :     case file_mode::read:
     102             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     103             :         s = L"rb";
     104             :     #else
     105           2 :         s = "rb";
     106             :     #endif
     107           2 :         break;
     108             : 
     109           1 :     case file_mode::scan:
     110             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     111             :         s = L"rbS";
     112             :     #else
     113           1 :         s = "rb";
     114             :     #endif
     115           1 :         break;
     116             : 
     117          10 :     case file_mode::write:
     118             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     119             :         s = L"wb+";
     120             :     #else
     121          10 :         s = "wb+";
     122             :     #endif
     123          10 :         break;
     124             : 
     125           2 :     case file_mode::write_new:
     126             :     {
     127             : #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     128             : # if (defined(BOOST_MSVC) && BOOST_MSVC >= 1910) || (defined(_MSVC_STL_VERSION) && _MSVC_STL_VERSION >= 141)
     129             :         s = L"wbx";
     130             : # else
     131             :         std::FILE* f0;
     132             :         auto const ev = ::_wfopen_s(&f0, unicode_path.c_str(), L"rb");
     133             :         if(! ev)
     134             :         {
     135             :             std::fclose(f0);
     136             :             ec = make_error_code(
     137             :                 system::errc::file_exists);
     138             :             return;
     139             :         }
     140             :         else if(ev !=
     141             :             system::errc::no_such_file_or_directory)
     142             :         {
     143             :             ec.assign(ev,
     144             :                 system::generic_category());
     145             :             return;
     146             :         }
     147             :         s = L"wb";
     148             : # endif
     149             : #else
     150           2 :         s = "wbx";
     151             : #endif
     152           2 :         break;
     153             :     }
     154             : 
     155           2 :     case file_mode::write_existing:
     156             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     157             :         s = L"rb+";
     158             :     #else
     159           2 :         s = "rb+";
     160             :     #endif
     161           2 :         break;
     162             : 
     163           2 :     case file_mode::append:
     164             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     165             :         s = L"ab";
     166             :     #else
     167           2 :         s = "ab";
     168             :     #endif
     169           2 :         break;
     170             : 
     171           2 :     case file_mode::append_existing:
     172             :     {
     173             : #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     174             :         std::FILE* f0;
     175             :         auto const ev =
     176             :             ::_wfopen_s(&f0, unicode_path.c_str(), L"rb+");
     177             :         if(ev)
     178             :         {
     179             :             ec.assign(ev,
     180             :                 system::generic_category());
     181             :             return;
     182             :         }
     183             : #else
     184             :         auto const f0 =
     185           2 :             std::fopen(path, "rb+");
     186           2 :         if(! f0)
     187             :         {
     188           1 :             ec.assign(errno,
     189             :                 system::generic_category());
     190           1 :             return;
     191             :         }
     192             : #endif
     193           1 :         std::fclose(f0);
     194             :     #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     195             :         s = L"ab";
     196             :     #else
     197           1 :         s = "ab";
     198             :     #endif
     199           1 :         break;
     200             :     }
     201             :     }
     202             : 
     203             : #if defined(BOOST_MSVC) || defined(_MSVC_STL_VERSION)
     204             :     auto const ev = ::_wfopen_s(
     205             :         &f_, unicode_path.c_str(), s);
     206             :     if(ev)
     207             :     {
     208             :         f_ = nullptr;
     209             :         ec.assign(ev,
     210             :             system::generic_category());
     211             :         return;
     212             :     }
     213             : #else
     214          20 :     f_ = std::fopen(path, s);
     215          20 :     if(! f_)
     216             :     {
     217           2 :         ec.assign(errno,
     218             :             system::generic_category());
     219           2 :         return;
     220             :     }
     221             : #endif
     222             : }
     223             : 
     224             : std::uint64_t
     225           2 : file_stdio::
     226             : size(
     227             :     system::error_code& ec) const
     228             : {
     229           2 :     if(! f_)
     230             :     {
     231             :         ec = make_error_code(
     232           1 :             system::errc::bad_file_descriptor);
     233           1 :         return 0;
     234             :     }
     235           1 :     long pos = std::ftell(f_);
     236           1 :     if(pos == -1L)
     237             :     {
     238           0 :         ec.assign(errno,
     239             :             system::generic_category());
     240           0 :         return 0;
     241             :     }
     242           1 :     int result = std::fseek(f_, 0, SEEK_END);
     243           1 :     if(result != 0)
     244             :     {
     245           0 :         ec.assign(errno,
     246             :             system::generic_category());
     247           0 :         return 0;
     248             :     }
     249           1 :     long size = std::ftell(f_);
     250           1 :     if(size == -1L)
     251             :     {
     252           0 :         ec.assign(errno,
     253             :             system::generic_category());
     254           0 :         std::fseek(f_, pos, SEEK_SET);
     255           0 :         return 0;
     256             :     }
     257           1 :     result = std::fseek(f_, pos, SEEK_SET);
     258           1 :     if(result != 0)
     259           0 :         ec.assign(errno,
     260             :             system::generic_category());
     261             :     else
     262           1 :         ec = {};
     263           1 :     return size;
     264             : }
     265             : 
     266             : std::uint64_t
     267           3 : file_stdio::
     268             : pos(
     269             :     system::error_code& ec) const
     270             : {
     271           3 :     if(! f_)
     272             :     {
     273             :         ec = make_error_code(
     274           1 :             system::errc::bad_file_descriptor);
     275           1 :         return 0;
     276             :     }
     277           2 :     long pos = std::ftell(f_);
     278           2 :     if(pos == -1L)
     279             :     {
     280           0 :         ec.assign(errno,
     281             :             system::generic_category());
     282           0 :         return 0;
     283             :     }
     284           2 :     ec = {};
     285           2 :     return pos;
     286             : }
     287             : 
     288             : void
     289           2 : file_stdio::
     290             : seek(std::uint64_t offset,
     291             :     system::error_code& ec)
     292             : {
     293           2 :     if(! f_)
     294             :     {
     295             :         ec = make_error_code(
     296           1 :             system::errc::bad_file_descriptor);
     297           1 :         return;
     298             :     }
     299           1 :     if(offset > static_cast<std::uint64_t>((std::numeric_limits<long>::max)()))
     300             :     {
     301             :         ec = make_error_code(
     302           0 :             system::errc::invalid_seek);
     303           0 :         return;
     304             :     }
     305           1 :     int result = std::fseek(f_,
     306             :         static_cast<long>(offset), SEEK_SET);
     307           1 :     if(result != 0)
     308           0 :         ec.assign(errno,
     309             :             system::generic_category());
     310             :     else
     311           1 :         ec = {};
     312             : }
     313             : 
     314             : std::size_t
     315           3 : file_stdio::
     316             : read(void* buffer, std::size_t n,
     317             :     system::error_code& ec) const
     318             : {
     319           3 :     if(! f_)
     320             :     {
     321             :         ec = make_error_code(
     322           1 :             system::errc::bad_file_descriptor);
     323           1 :         return 0;
     324             :     }
     325           2 :     auto nread = std::fread(buffer, 1, n, f_);
     326           2 :     if(std::ferror(f_))
     327             :     {
     328           0 :         ec.assign(errno,
     329             :             system::generic_category());
     330           0 :         return 0;
     331             :     }
     332           2 :     return nread;
     333             : }
     334             : 
     335             : std::size_t
     336           5 : file_stdio::
     337             : write(void const* buffer, std::size_t n,
     338             :     system::error_code& ec)
     339             : {
     340           5 :     if(! f_)
     341             :     {
     342             :         ec = make_error_code(
     343           1 :             system::errc::bad_file_descriptor);
     344           1 :         return 0;
     345             :     }
     346           4 :     auto nwritten = std::fwrite(buffer, 1, n, f_);
     347           4 :     if(std::ferror(f_))
     348             :     {
     349           0 :         ec.assign(errno,
     350             :             system::generic_category());
     351           0 :         return 0;
     352             :     }
     353           4 :     return nwritten;
     354             : }
     355             : 
     356             : } // http_proto
     357             : } // boost
     358             : 
     359             : #endif

Generated by: LCOV version 1.15