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

Generated by: LCOV version 2.1