LCOV - code coverage report
Current view: top level - libs/http_proto/src/file_stdio.cpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 84.9 % 126 107
Test Date: 2024-07-12 15:42:45 Functions: 100.0 % 11 11

            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              : ~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            1 :         ec = make_error_code(
     230              :             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            1 :         ec = make_error_code(
     272              :             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            1 :         ec = make_error_code(
     294              :             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            0 :         ec = make_error_code(
     300              :             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            1 :         ec = make_error_code(
     320              :             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            1 :         ec = make_error_code(
     341              :             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 2.1