mirror of
https://github.com/boostorg/beast.git
synced 2025-08-05 15:54:46 +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
|
void
|
||||||
reset(File&& file, error_code& ec);
|
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>
|
template<class File>
|
||||||
@@ -210,8 +223,29 @@ reset(File&& file, error_code& ec)
|
|||||||
|
|
||||||
// Cache the size
|
// Cache the size
|
||||||
file_size_ = file_.size(ec);
|
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
|
// This is called from message::payload_size
|
||||||
template<class File>
|
template<class File>
|
||||||
std::uint64_t
|
std::uint64_t
|
||||||
|
@@ -94,7 +94,7 @@ struct basic_file_body<file_win32>
|
|||||||
std::uint64_t
|
std::uint64_t
|
||||||
size() const
|
size() const
|
||||||
{
|
{
|
||||||
return size_;
|
return last_ - first_;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -105,6 +105,9 @@ struct basic_file_body<file_win32>
|
|||||||
|
|
||||||
void
|
void
|
||||||
reset(file_win32&& file, error_code& ec);
|
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();
|
close();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
first_ = 0;
|
|
||||||
|
first_ = file_.pos(ec);
|
||||||
|
if(ec)
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
last_ = size_;
|
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 {
|
namespace detail {
|
||||||
|
@@ -17,6 +17,7 @@
|
|||||||
#include <boost/beast/core/static_string.hpp>
|
#include <boost/beast/core/static_string.hpp>
|
||||||
#include <boost/beast/http/parser.hpp>
|
#include <boost/beast/http/parser.hpp>
|
||||||
#include <boost/beast/http/serializer.hpp>
|
#include <boost/beast/http/serializer.hpp>
|
||||||
|
#include <boost/beast/http/string_body.hpp>
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
#include <boost/asio/error.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
|
struct temp_file
|
||||||
{
|
{
|
||||||
temp_file(std::ostream& logger)
|
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
|
void
|
||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
@@ -212,6 +311,17 @@ public:
|
|||||||
fileBodyUnexpectedEofOnGet<file_win32>();
|
fileBodyUnexpectedEofOnGet<file_win32>();
|
||||||
#endif
|
#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