aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/yson_pull/detail/byte_reader.h
diff options
context:
space:
mode:
Diffstat (limited to 'library/cpp/yson_pull/detail/byte_reader.h')
-rw-r--r--library/cpp/yson_pull/detail/byte_reader.h74
1 files changed, 74 insertions, 0 deletions
diff --git a/library/cpp/yson_pull/detail/byte_reader.h b/library/cpp/yson_pull/detail/byte_reader.h
new file mode 100644
index 0000000000..7cea50d323
--- /dev/null
+++ b/library/cpp/yson_pull/detail/byte_reader.h
@@ -0,0 +1,74 @@
+#pragma once
+
+#include "cescape.h"
+#include "fail.h"
+#include "stream_counter.h"
+
+#include <library/cpp/yson_pull/input.h>
+
+namespace NYsonPull {
+ namespace NDetail {
+ template <class StreamCounter>
+ class byte_reader {
+ NYsonPull::NInput::IStream& stream_;
+ StreamCounter stream_counter_;
+
+ public:
+ byte_reader(NYsonPull::NInput::IStream& stream)
+ : stream_(stream)
+ {
+ }
+
+ // const-ness added to prevent direct stream mutation
+ const NYsonPull::NInput::IStream& stream() {
+ return stream_;
+ }
+
+ template <typename... Args>
+ ATTRIBUTE(noinline, cold)
+ void fail[[noreturn]](const char* msg, Args&&... args) {
+ NYsonPull::NDetail::fail(
+ stream_counter_.info(),
+ msg,
+ std::forward<Args>(args)...);
+ }
+
+ template <bool AllowFinish>
+ void fill_buffer() {
+ stream_.fill_buffer();
+
+ if (!AllowFinish) {
+ auto& buf = stream_.buffer();
+ if (Y_UNLIKELY(buf.is_empty() && stream_.at_end())) {
+ fail("Premature end of stream");
+ }
+ }
+ }
+
+ void fill_buffer() {
+ return fill_buffer<true>();
+ }
+
+ template <bool AllowFinish>
+ ui8 get_byte() {
+ fill_buffer<AllowFinish>();
+ auto& buf = stream_.buffer();
+ return !buf.is_empty()
+ ? *buf.pos()
+ : ui8{'\0'};
+ }
+
+ ui8 get_byte() {
+ return get_byte<true>();
+ }
+
+ void advance(size_t bytes) {
+ auto& buf = stream_.buffer();
+ stream_counter_.update(
+ buf.pos(),
+ buf.pos() + bytes);
+ buf.advance(bytes);
+ }
+ };
+ }
+}