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

Generated by: LCOV version 1.15