-
Notifications
You must be signed in to change notification settings - Fork 439
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
adds
ranges::basic_unformatted_istream_view
`istream_view` is only useful if the input to be formatted on read and `std::istreambuf_iterator` only works with types that have a `std::char_traits` specialisation. The purpose of `unformatted_istream_view` is to read from an istream object without formatting (so integers will be read as binary rather than as text).
- Loading branch information
Showing
5 changed files
with
212 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -237,3 +237,6 @@ $RECYCLE.BIN/ | |
\#*# | ||
.#* | ||
/CMakeSettings.json | ||
|
||
# clangd cache | ||
.cache/clangd/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,119 @@ | ||
/// \file | ||
// Range v3 library | ||
// | ||
// Copyright Eric Niebler 2013-present | ||
// Copyright Google LLC 2020-present | ||
// | ||
// Use, modification and distribution is subject to 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) | ||
// | ||
// Project home: https://github.com/ericniebler/range-v3 | ||
// | ||
|
||
#ifndef RANGES_V3_VIEW_UNFORMATTED_ISTREAM_HPP | ||
#define RANGES_V3_VIEW_UNFORMATTED_ISTREAM_HPP | ||
|
||
#include <istream> | ||
|
||
#include <range/v3/range_fwd.hpp> | ||
|
||
#include <range/v3/iterator/default_sentinel.hpp> | ||
#include <range/v3/utility/semiregular_box.hpp> | ||
#include <range/v3/utility/static_const.hpp> | ||
#include <range/v3/view/facade.hpp> | ||
|
||
#include <range/v3/detail/prologue.hpp> | ||
|
||
namespace ranges | ||
{ | ||
/// \addtogroup group-views | ||
/// @{ | ||
template<typename Val, typename CharT = char, typename Traits = std::char_traits<CharT>> | ||
struct basic_unformatted_istream_view | ||
: view_facade<basic_unformatted_istream_view<Val, CharT, Traits>, unknown> | ||
{ | ||
private: | ||
friend range_access; | ||
std::basic_istream<CharT, Traits> * sin_; | ||
semiregular_box_t<Val> obj_; | ||
struct cursor | ||
{ | ||
private: | ||
friend range_access; | ||
using single_pass = std::true_type; | ||
basic_unformatted_istream_view * rng_ = nullptr; | ||
|
||
public: | ||
cursor() = default; | ||
explicit cursor(basic_unformatted_istream_view * rng) noexcept | ||
: rng_(rng) | ||
{} | ||
void next() | ||
{ | ||
rng_->next(); | ||
} | ||
Val & read() const noexcept | ||
{ | ||
return rng_->cached(); | ||
} | ||
bool equal(default_sentinel_t) const noexcept | ||
{ | ||
return !rng_->sin_; | ||
} | ||
bool equal(cursor that) const noexcept | ||
{ | ||
return !rng_->sin_ == !that.rng_->sin_; | ||
} | ||
}; | ||
void next() | ||
{ | ||
if(!sin_->read(reinterpret_cast<CharT*>(std::addressof(cached())), sizeof(Val))) { | ||
sin_ = nullptr; | ||
} | ||
} | ||
cursor begin_cursor() | ||
{ | ||
return cursor{this}; | ||
} | ||
|
||
public: | ||
basic_unformatted_istream_view() = default; | ||
explicit basic_unformatted_istream_view(std::istream & sin) | ||
noexcept(std::is_nothrow_default_constructible<Val>::value) | ||
: sin_(&sin) | ||
, obj_{} | ||
{ | ||
// The current `value_` is considered stale, so we'd better update it (otherwise the | ||
// first value in the range will *always* be `Val()`.) | ||
next(); | ||
} | ||
Val & cached() noexcept | ||
{ | ||
return obj_; | ||
} | ||
}; | ||
|
||
/// \cond | ||
namespace _unformatted_istream_ | ||
{ | ||
/// \endcond | ||
template(typename Val, typename CharT, typename Traits)( | ||
/// \pre | ||
requires copy_constructible<Val> AND default_constructible<Val>) | ||
inline basic_unformatted_istream_view<Val, CharT, Traits> | ||
unformatted_istream_view(std::basic_istream<CharT, Traits> & sin) | ||
{ | ||
return basic_unformatted_istream_view<Val>{sin}; | ||
} | ||
/// \cond | ||
} // namespace _unformatted_istream_ | ||
using namespace _unformatted_istream_; | ||
/// \endcond | ||
/// @} | ||
} // namespace ranges | ||
|
||
#include <range/v3/detail/epilogue.hpp> | ||
|
||
#endif |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
// Range v3 library | ||
// | ||
// Copyright Eric Niebler 2014-present | ||
// Copyright Google LLC 2020-present | ||
// | ||
// Use, modification and distribution is subject to 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) | ||
// | ||
// Project home: https://github.com/ericniebler/range-v3 | ||
#include <range/v3/view/unformatted_istream.hpp> | ||
|
||
#include <range/v3/algorithm/copy.hpp> | ||
#include <range/v3/range/conversion.hpp> | ||
#include <range/v3/view/for_each.hpp> | ||
#include <range/v3/view/reverse.hpp> | ||
#include <range/v3/view/sliding.hpp> | ||
#include <range/v3/view/stride.hpp> | ||
#include <string> | ||
#include <sstream> | ||
#include <vector> | ||
|
||
#include <range/v3/iterator.hpp> | ||
|
||
#include "../simple_test.hpp" | ||
#include "../test_utils.hpp" | ||
|
||
namespace rv = ranges::views; | ||
|
||
namespace std { | ||
template<typename T> | ||
std::ostream& operator<<(std::ostream& os, std::vector<T> const& v) | ||
{ | ||
os << std::hex; | ||
ranges::copy(v, ::ranges::ostream_iterator(os, " ")); | ||
return os; | ||
} | ||
} | ||
|
||
int main() | ||
{ | ||
{ | ||
#if defined(__BYTE_ORDER__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ | ||
auto const input = std::vector<std::string>(3, "\x21\x22\x23\x24"); | ||
#else | ||
auto const input = std::vector<std::string>{ | ||
"\x21\x22\x23\x24", | ||
"\x22\x21\x24\x23", | ||
"\x24\x23\x22\x21", | ||
}; | ||
#endif // endianness | ||
{ | ||
auto in = std::istringstream(input[0]); | ||
auto const expected = std::vector<std::uint8_t>{0x21, 0x22, 0x23, 0x24}; | ||
auto const actual = ranges::unformatted_istream_view<std::uint8_t>(in) | ranges::to<std::vector>; | ||
CHECK(actual == expected); | ||
} | ||
|
||
{ | ||
auto in = std::istringstream(input[1]); | ||
auto const expected = std::vector<std::uint16_t>{0x2122, 0x2324}; | ||
auto const actual = ranges::unformatted_istream_view<std::uint16_t>(in) | ranges::to<std::vector>; | ||
CHECK(actual == expected); | ||
} | ||
{ | ||
auto in = std::istringstream(input[2]); | ||
auto const expected = std::vector<std::uint32_t>{0x21222324}; | ||
auto const actual = ranges::unformatted_istream_view<std::uint32_t>(in) | ranges::to<std::vector>; | ||
CHECK(actual == expected); | ||
} | ||
{ | ||
auto in = std::istringstream(input[2]); | ||
auto const actual = ranges::unformatted_istream_view<std::uint64_t>(in) | ranges::to<std::vector>; | ||
CHECK(in.fail()); | ||
} | ||
#if __cplusplus >= 201703L | ||
{ | ||
auto in = std::istringstream(input[2]); | ||
auto const expected = std::vector<float>{0x1.4446480000000000179Dp-61f}; | ||
auto const actual = ranges::unformatted_istream_view<float>(in) | ranges::to<std::vector>; | ||
CHECK(actual == expected); | ||
} | ||
#endif // __cplusplus >= 201703L | ||
} | ||
|
||
return ::test_result(); | ||
} |