//
-// Copyright (c) 2015-2016 Vinnie Falco (vinnie dot falco at gmail dot com)
+// Copyright (c) 2015-2019 Vinnie Falco (vinnie dot falco at gmail dot com)
//
// Distributed under the Boost Software License, Version 1.0. (See accompanying
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
#ifndef BOOST_BEAST_CORE_IMPL_FILE_STDIO_IPP
#define BOOST_BEAST_CORE_IMPL_FILE_STDIO_IPP
+#include <boost/beast/core/file_stdio.hpp>
+#include <boost/config/workaround.hpp>
+#include <boost/core/exchange.hpp>
#include <limits>
namespace boost {
namespace beast {
-inline
file_stdio::
~file_stdio()
{
fclose(f_);
}
-inline
file_stdio::
file_stdio(file_stdio&& other)
- : f_(other.f_)
+ : f_(boost::exchange(other.f_, nullptr))
{
- other.f_ = nullptr;
}
-inline
file_stdio&
file_stdio::
operator=(file_stdio&& other)
return *this;
}
-inline
void
file_stdio::
native_handle(FILE* f)
f_ = f;
}
-inline
void
file_stdio::
close(error_code& ec)
return;
}
}
- ec.assign(0, ec.category());
+ ec = {};
}
-inline
void
file_stdio::
open(char const* path, file_mode mode, error_code& ec)
switch(mode)
{
default:
- case file_mode::read: s = "rb"; break;
- case file_mode::scan: s = "rb"; break;
- case file_mode::write: s = "wb"; break;
- case file_mode::write_new: s = "wbx"; break;
- case file_mode::write_existing: s = "wb"; break;
- case file_mode::append: s = "ab"; break;
- case file_mode::append_new: s = "abx"; break;
- case file_mode::append_existing: s = "ab"; break;
- }
-#if BOOST_MSVC
- auto const ev = fopen_s(&f_, path, s);
+ case file_mode::read:
+ s = "rb";
+ break;
+
+ case file_mode::scan:
+ #ifdef BOOST_MSVC
+ s = "rbS";
+ #else
+ s = "rb";
+ #endif
+ break;
+
+ case file_mode::write:
+ s = "wb+";
+ break;
+
+ case file_mode::write_new:
+ {
+#if BOOST_WORKAROUND(BOOST_MSVC, < 1910)
+ FILE* f0;
+ auto const ev = ::fopen_s(&f0, path, "rb");
+ if(! ev)
+ {
+ std::fclose(f0);
+ ec = make_error_code(errc::file_exists);
+ return;
+ }
+ else if(ev !=
+ errc::no_such_file_or_directory)
+ {
+ ec.assign(ev, generic_category());
+ return;
+ }
+ s = "wb";
+#else
+
+ s = "wbx";
+#endif
+ break;
+ }
+
+ case file_mode::write_existing:
+ s = "rb+";
+ break;
+
+ case file_mode::append:
+ s = "ab";
+ break;
+
+ case file_mode::append_existing:
+ {
+#ifdef BOOST_MSVC
+ FILE* f0;
+ auto const ev =
+ ::fopen_s(&f0, path, "rb+");
+ if(ev)
+ {
+ ec.assign(ev, generic_category());
+ return;
+ }
+#else
+ auto const f0 =
+ std::fopen(path, "rb+");
+ if(! f0)
+ {
+ ec.assign(errno, generic_category());
+ return;
+ }
+#endif
+ std::fclose(f0);
+ s = "ab";
+ break;
+ }
+ }
+
+#ifdef BOOST_MSVC
+ auto const ev = ::fopen_s(&f_, path, s);
if(ev)
{
f_ = nullptr;
return;
}
#endif
- ec.assign(0, ec.category());
+ ec = {};
}
-inline
std::uint64_t
file_stdio::
size(error_code& ec) const
{
if(! f_)
{
- ec = make_error_code(errc::invalid_argument);
+ ec = make_error_code(errc::bad_file_descriptor);
return 0;
}
long pos = std::ftell(f_);
if(result != 0)
ec.assign(errno, generic_category());
else
- ec.assign(0, ec.category());
+ ec = {};
return size;
}
-inline
std::uint64_t
file_stdio::
pos(error_code& ec) const
{
if(! f_)
{
- ec = make_error_code(errc::invalid_argument);
+ ec = make_error_code(errc::bad_file_descriptor);
return 0;
}
long pos = std::ftell(f_);
ec.assign(errno, generic_category());
return 0;
}
- ec.assign(0, ec.category());
+ ec = {};
return pos;
}
-inline
void
file_stdio::
seek(std::uint64_t offset, error_code& ec)
{
if(! f_)
{
- ec = make_error_code(errc::invalid_argument);
+ ec = make_error_code(errc::bad_file_descriptor);
return;
}
- if(offset > (std::numeric_limits<long>::max)())
+ if(offset > static_cast<std::uint64_t>(std::numeric_limits<long>::max()))
{
ec = make_error_code(errc::invalid_seek);
return;
if(result != 0)
ec.assign(errno, generic_category());
else
- ec.assign(0, ec.category());
+ ec = {};
}
-inline
std::size_t
file_stdio::
read(void* buffer, std::size_t n, error_code& ec) const
{
if(! f_)
{
- ec = make_error_code(errc::invalid_argument);
+ ec = make_error_code(errc::bad_file_descriptor);
return 0;
}
auto nread = std::fread(buffer, 1, n, f_);
return nread;
}
-inline
std::size_t
file_stdio::
write(void const* buffer, std::size_t n, error_code& ec)
{
if(! f_)
{
- ec = make_error_code(errc::invalid_argument);
+ ec = make_error_code(errc::bad_file_descriptor);
return 0;
}
auto nwritten = std::fwrite(buffer, 1, n, f_);