buffered_io.h 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #pragma once
  2. #include <util/system/yassert.h>
  3. #include <util/generic/utility.h>
  4. #include <util/generic/ylimits.h>
  5. #include <string.h>
  6. struct IBinaryStream {
  7. virtual ~IBinaryStream() = default;
  8. inline i64 Write(const void* userBuffer, i64 size) {
  9. if (size <= Max<int>()) {
  10. return WriteImpl(userBuffer, static_cast<int>(size));
  11. } else {
  12. return LongWrite(userBuffer, size);
  13. }
  14. }
  15. inline i64 Read(void* userBuffer, i64 size) {
  16. if (size <= Max<int>()) {
  17. return ReadImpl(userBuffer, static_cast<int>(size));
  18. } else {
  19. return LongRead(userBuffer, size);
  20. }
  21. }
  22. virtual bool IsValid() const = 0;
  23. virtual bool IsFailed() const = 0;
  24. private:
  25. virtual int WriteImpl(const void* userBuffer, int size) = 0;
  26. virtual int ReadImpl(void* userBuffer, int size) = 0;
  27. i64 LongRead(void* userBuffer, i64 size);
  28. i64 LongWrite(const void* userBuffer, i64 size);
  29. };
  30. template <int N_SIZE = 16384>
  31. class TBufferedStream {
  32. char Buf[N_SIZE];
  33. i64 Pos, BufSize;
  34. IBinaryStream& Stream;
  35. bool bIsReading, bIsEof, bFailed;
  36. void ReadComplex(void* userBuffer, i64 size) {
  37. if (bIsEof) {
  38. memset(userBuffer, 0, size);
  39. return;
  40. }
  41. char* dst = (char*)userBuffer;
  42. i64 leftBytes = BufSize - Pos;
  43. memcpy(dst, Buf + Pos, leftBytes);
  44. dst += leftBytes;
  45. size -= leftBytes;
  46. Pos = BufSize = 0;
  47. if (size > N_SIZE) {
  48. i64 n = Stream.Read(dst, size);
  49. bFailed = Stream.IsFailed();
  50. if (n != size) {
  51. bIsEof = true;
  52. memset(dst + n, 0, size - n);
  53. }
  54. } else {
  55. BufSize = Stream.Read(Buf, N_SIZE);
  56. bFailed = Stream.IsFailed();
  57. if (BufSize == 0)
  58. bIsEof = true;
  59. Read(dst, size);
  60. }
  61. }
  62. void WriteComplex(const void* userBuffer, i64 size) {
  63. Flush();
  64. if (size >= N_SIZE) {
  65. Stream.Write(userBuffer, size);
  66. bFailed = Stream.IsFailed();
  67. } else
  68. Write(userBuffer, size);
  69. }
  70. void operator=(const TBufferedStream&) {
  71. }
  72. public:
  73. TBufferedStream(bool bRead, IBinaryStream& stream)
  74. : Pos(0)
  75. , BufSize(0)
  76. , Stream(stream)
  77. , bIsReading(bRead)
  78. , bIsEof(false)
  79. , bFailed(false)
  80. {
  81. }
  82. ~TBufferedStream() {
  83. if (!bIsReading)
  84. Flush();
  85. }
  86. void Flush() {
  87. Y_ASSERT(!bIsReading);
  88. if (bIsReading)
  89. return;
  90. Stream.Write(Buf, Pos);
  91. bFailed = Stream.IsFailed();
  92. Pos = 0;
  93. }
  94. bool IsEof() const {
  95. return bIsEof;
  96. }
  97. inline void Read(void* userBuffer, i64 size) {
  98. Y_ASSERT(bIsReading);
  99. if (!bIsEof && size + Pos <= BufSize) {
  100. memcpy(userBuffer, Buf + Pos, size);
  101. Pos += size;
  102. return;
  103. }
  104. ReadComplex(userBuffer, size);
  105. }
  106. inline void Write(const void* userBuffer, i64 size) {
  107. Y_ASSERT(!bIsReading);
  108. if (Pos + size < N_SIZE) {
  109. memcpy(Buf + Pos, userBuffer, size);
  110. Pos += size;
  111. return;
  112. }
  113. WriteComplex(userBuffer, size);
  114. }
  115. bool IsValid() const {
  116. return Stream.IsValid();
  117. }
  118. bool IsFailed() const {
  119. return bFailed;
  120. }
  121. };