byte_reader.h 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #pragma once
  2. #include "cescape.h"
  3. #include "fail.h"
  4. #include "stream_counter.h"
  5. #include <library/cpp/yson_pull/input.h>
  6. namespace NYsonPull {
  7. namespace NDetail {
  8. template <class StreamCounter>
  9. class byte_reader {
  10. NYsonPull::NInput::IStream& stream_;
  11. StreamCounter stream_counter_;
  12. public:
  13. byte_reader(NYsonPull::NInput::IStream& stream)
  14. : stream_(stream)
  15. {
  16. }
  17. // const-ness added to prevent direct stream mutation
  18. const NYsonPull::NInput::IStream& stream() {
  19. return stream_;
  20. }
  21. template <typename... Args>
  22. ATTRIBUTE(noinline, cold)
  23. void fail[[noreturn]](const char* msg, Args&&... args) {
  24. NYsonPull::NDetail::fail(
  25. stream_counter_.info(),
  26. msg,
  27. std::forward<Args>(args)...);
  28. }
  29. template <bool AllowFinish>
  30. void fill_buffer() {
  31. stream_.fill_buffer();
  32. if (!AllowFinish) {
  33. auto& buf = stream_.buffer();
  34. if (Y_UNLIKELY(buf.is_empty() && stream_.at_end())) {
  35. fail("Premature end of stream");
  36. }
  37. }
  38. }
  39. void fill_buffer() {
  40. return fill_buffer<true>();
  41. }
  42. template <bool AllowFinish>
  43. ui8 get_byte() {
  44. fill_buffer<AllowFinish>();
  45. auto& buf = stream_.buffer();
  46. return !buf.is_empty()
  47. ? *buf.pos()
  48. : ui8{'\0'};
  49. }
  50. ui8 get_byte() {
  51. return get_byte<true>();
  52. }
  53. void advance(size_t bytes) {
  54. auto& buf = stream_.buffer();
  55. stream_counter_.update(
  56. buf.pos(),
  57. buf.pos() + bytes);
  58. buf.advance(bytes);
  59. }
  60. };
  61. }
  62. }