mirror of
https://github.com/boostorg/beast.git
synced 2025-08-03 06:44:39 +02:00
beast file_body & file support seek.
win32 file_body handles seek correctly. Added seek to win32 file. file_body_writer handles offsets.
This commit is contained in:
committed by
Klemens Morgenstern
parent
4ff4c79d5b
commit
1d965752b2
@@ -160,6 +160,19 @@ public:
|
||||
*/
|
||||
void
|
||||
reset(File&& file, error_code& ec);
|
||||
|
||||
/** Set the cursor position of the file.
|
||||
|
||||
This function can be used to move the cursor of the file ahead
|
||||
so that only a part gets read. This file will also adjust the
|
||||
value_type, in case the file is already part of a body.
|
||||
|
||||
@param offset The offset in bytes from the beginning of the file
|
||||
|
||||
@param ec Set to the error, if any occurred
|
||||
*/
|
||||
|
||||
void seek(std::uint64_t offset, error_code& ec);
|
||||
};
|
||||
|
||||
template<class File>
|
||||
@@ -210,8 +223,29 @@ reset(File&& file, error_code& ec)
|
||||
|
||||
// Cache the size
|
||||
file_size_ = file_.size(ec);
|
||||
|
||||
// Consider the offset
|
||||
if (!ec)
|
||||
file_size_ -= file_.pos(ec);
|
||||
}
|
||||
|
||||
template<class File>
|
||||
void
|
||||
basic_file_body<File>::
|
||||
value_type::
|
||||
seek(std::uint64_t offset, error_code& ec)
|
||||
{
|
||||
file_.seek(offset, ec);
|
||||
// Cache the size
|
||||
if (!ec)
|
||||
file_size_ = file_.size(ec);
|
||||
|
||||
// Consider the offset
|
||||
if (!ec)
|
||||
file_size_ -= file_.pos(ec);
|
||||
}
|
||||
|
||||
|
||||
// This is called from message::payload_size
|
||||
template<class File>
|
||||
std::uint64_t
|
||||
|
@@ -94,7 +94,7 @@ struct basic_file_body<file_win32>
|
||||
std::uint64_t
|
||||
size() const
|
||||
{
|
||||
return size_;
|
||||
return last_ - first_;
|
||||
}
|
||||
|
||||
void
|
||||
@@ -105,6 +105,9 @@ struct basic_file_body<file_win32>
|
||||
|
||||
void
|
||||
reset(file_win32&& file, error_code& ec);
|
||||
|
||||
void
|
||||
seek(std::uint64_t offset, error_code& ec);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
@@ -284,11 +287,29 @@ reset(file_win32&& file, error_code& ec)
|
||||
close();
|
||||
return;
|
||||
}
|
||||
first_ = 0;
|
||||
|
||||
first_ = file_.pos(ec);
|
||||
if(ec)
|
||||
{
|
||||
close();
|
||||
return;
|
||||
}
|
||||
|
||||
last_ = size_;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline
|
||||
void
|
||||
basic_file_body<file_win32>::
|
||||
value_type::
|
||||
seek(std::uint64_t offset, error_code& ec)
|
||||
{
|
||||
first_ = offset;
|
||||
file_.seek(offset, ec);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace detail {
|
||||
|
@@ -17,6 +17,7 @@
|
||||
#include <boost/beast/core/static_string.hpp>
|
||||
#include <boost/beast/http/parser.hpp>
|
||||
#include <boost/beast/http/serializer.hpp>
|
||||
#include <boost/beast/http/string_body.hpp>
|
||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/asio/error.hpp>
|
||||
@@ -43,6 +44,23 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct string_parser
|
||||
{
|
||||
parser<false, string_body> p;
|
||||
std::size_t last_consumption;
|
||||
template<class ConstBufferSequence>
|
||||
void
|
||||
operator()(error_code&, ConstBufferSequence const& buffers)
|
||||
{
|
||||
error_code ec;
|
||||
BEAST_EXPECT(!p.is_done());
|
||||
if (!p.is_done())
|
||||
last_consumption = p.put(buffers, ec);
|
||||
|
||||
BEAST_EXPECT(!ec);
|
||||
}
|
||||
};
|
||||
|
||||
struct temp_file
|
||||
{
|
||||
temp_file(std::ostream& logger)
|
||||
@@ -193,6 +211,87 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template<class File, bool useReset>
|
||||
void
|
||||
readPartialFile()
|
||||
{
|
||||
|
||||
auto temp = temp_file(log);
|
||||
|
||||
error_code ec;
|
||||
string_view const ten =
|
||||
"0123456789"; // 40
|
||||
// create the temporary file
|
||||
{
|
||||
std::ofstream fstemp(temp.path().native());
|
||||
std::size_t written = 0;
|
||||
std::size_t to_write = 2048;
|
||||
while (written < to_write)
|
||||
{
|
||||
auto size = (std::min)(ten.size(), to_write - written);
|
||||
fstemp << ten.substr(0, size);
|
||||
BEAST_EXPECT(fstemp.good());
|
||||
written += size;
|
||||
}
|
||||
fstemp.close();
|
||||
}
|
||||
|
||||
// open the file and read the header
|
||||
{
|
||||
using file_body_type = basic_file_body<File>;
|
||||
|
||||
typename file_body_type::value_type value;
|
||||
// opened in write mode so we can truncate later
|
||||
value.open(temp.path().string<std::string>().c_str(), file_mode::read, ec);
|
||||
BEAST_EXPECTS(!ec, ec.message());
|
||||
|
||||
response<basic_file_body<File>> res{status::ok, 11};
|
||||
res.set(field::server, "test");
|
||||
|
||||
if (useReset)
|
||||
{
|
||||
File f;
|
||||
f.open(temp.path().string<std::string>().c_str(), file_mode::read, ec);
|
||||
BEAST_EXPECTS(!ec, ec.message());
|
||||
f.seek(1005, ec); // so we start at char 5
|
||||
BEAST_EXPECTS(!ec, ec.message());
|
||||
res.body().reset(std::move(f), ec);
|
||||
BEAST_EXPECTS(!ec, ec.message());
|
||||
}
|
||||
else
|
||||
{
|
||||
res.body().open(temp.path().string<std::string>().c_str(), file_mode::read, ec);
|
||||
BEAST_EXPECTS(!ec, ec.message());
|
||||
res.body().seek(1005, ec); // so we start at char 5
|
||||
BEAST_EXPECTS(!ec, ec.message());
|
||||
}
|
||||
|
||||
res.prepare_payload();
|
||||
BEAST_EXPECT(res.payload_size().value_or(0) == (2048 - 1005));
|
||||
BEAST_EXPECTS(! ec, ec.message());
|
||||
|
||||
string_parser visit;
|
||||
serializer<false, basic_file_body<File>, fields> sr{res};
|
||||
|
||||
while (!sr.is_done())
|
||||
{
|
||||
sr.next(ec, visit);
|
||||
sr.consume(visit.last_consumption);
|
||||
}
|
||||
|
||||
BEAST_EXPECT(visit.p.is_header_done());
|
||||
BEAST_EXPECT(visit.p.content_length_remaining().value() == 0);
|
||||
|
||||
BEAST_EXPECT(visit.p.is_done());
|
||||
|
||||
auto data = visit.p.get();
|
||||
|
||||
BEAST_EXPECT(data.payload_size().value_or(0) == (2048 - 1005));
|
||||
BEAST_EXPECT(data.body().size() == (2048 - 1005));
|
||||
BEAST_EXPECT(data.body().front() == '5');
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
run() override
|
||||
{
|
||||
@@ -212,6 +311,17 @@ public:
|
||||
fileBodyUnexpectedEofOnGet<file_win32>();
|
||||
#endif
|
||||
|
||||
readPartialFile<file_stdio, true>();
|
||||
readPartialFile<file_stdio, false>();
|
||||
#if BOOST_BEAST_USE_POSIX_FILE
|
||||
readPartialFile<file_posix, true>();
|
||||
readPartialFile<file_posix, false>();
|
||||
#endif
|
||||
#if BOOST_BEAST_USE_WIN32_FILE
|
||||
readPartialFile<file_win32, true>();
|
||||
readPartialFile<file_win32, false>();
|
||||
#endif
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user