Audacity 3.2.0
BufferedStreamReader.h
Go to the documentation of this file.
1/**********************************************************************
2
3 Audacity: A Digital Audio Editor
4
5 BufferedStreamReader.h
6
7 Dmitry Vedenko
8
9**********************************************************************/
10
11#pragma once
12
13#include <vector>
14#include <cstddef>
15#include <cstdint>
16#include <type_traits>
17
23class UTILITY_API BufferedStreamReader /* not final */
24{
25public:
26 static constexpr size_t RequiredAlignment = 8;
27
28 explicit BufferedStreamReader(size_t bufferSize = 4096);
29
31 size_t Read(void* buffer, size_t maxBytes);
32
34 template<typename ValueType>
35 std::enable_if_t<sizeof(ValueType) <= RequiredAlignment, bool>
36 ReadValue(ValueType& value) /* ReadData may throw */
37 {
38 constexpr size_t valueSize = sizeof(ValueType);
39 const size_t availableBytes = mCurrentBytes - mCurrentIndex;
40
41 // In case of underflow - just fall back to general Read routine
42 if (availableBytes < valueSize)
43 return valueSize == Read(&value, valueSize);
44
45 // Special case for one bytes reads
46 if constexpr (valueSize == 1)
47 value = mBufferStart[mCurrentIndex];
48 else
49 value = UncheckedRead<ValueType>();
50
51 mCurrentIndex += valueSize;
52
53 return true;
54 }
55
57 bool Eof() const;
58
60 int GetC();
61
62protected:
64 virtual bool HasMoreData() const = 0;
66 virtual size_t ReadData(void* buffer, size_t maxBytes) = 0;
67
68private:
70 bool HandleUnderflow();
71
75 template<typename T>
76 T UncheckedRead() noexcept
77 {
78 T result;
79
80 // We know, that mBufferStart is always at least RequiredAlignment aligned
81 // Only mCurrentIndex alignment matters here
82
83 if ((mCurrentIndex % sizeof(T)) == 0)
84 {
85 // If the result is aligned - just read it from the memory
86 const void* ptr = mBufferStart + mCurrentIndex;
87 result = *static_cast<const T*>(ptr);
88 }
89 else
90 {
91 // Fallback to std::copy otherwise
92 const uint8_t* begin = mBufferStart + mCurrentIndex;
93 const uint8_t* end = begin + sizeof(T);
94 void* out = &result;
95
96 std::copy(begin, end, static_cast<uint8_t*>(out));
97 }
98
99 return result;
100 }
101
102 // Cache storage
103 std::vector<uint8_t> mBufferData;
104
105 // mBufferStart is aligned to RequiredAlignment bytes boundary.
106 // Both values below are initialized in the constructor.
107 uint8_t* mBufferStart;
109
110 size_t mCurrentIndex { 0 };
111 size_t mCurrentBytes { 0 };
112};
A facade-like class, that implements buffered reading from the underlying data stream.
std::enable_if_t< sizeof(ValueType)<=RequiredAlignment, bool > ReadValue(ValueType &value) { constexpr size_t valueSize=sizeof(ValueType);const size_t availableBytes=mCurrentBytes - mCurrentIndex;if(availableBytes< valueSize) return valueSize==Read(&value, valueSize);if constexpr(valueSize==1) value=mBufferStart[mCurrentIndex];else value=UncheckedRead< ValueType >();mCurrentIndex+=valueSize;return true;} bool Eof() const ;int GetC();protected:virtual bool HasMoreData() const=0;virtual size_t ReadData(void *buffer, size_t maxBytes)=0;private:bool HandleUnderflow();template< typename T > T UncheckedRead() noexcept { T result;if((mCurrentIndex % sizeof(T))==0) { const void *ptr=mBufferStart+mCurrentIndex;result=*static_cast< const T * >(ptr);} else { const uint8_t *begin=mBufferStart+mCurrentIndex;const uint8_t *end=begin+sizeof(T);void *out=&result;std::copy(begin, end, static_cast< uint8_t * >(out));} return result;} std::vector< uint8_t > mBufferData
Read a single value of ValueType, where sizeof(ValueType) <= 8 and value is aligned to the size bound...
const char * end(const char *str) noexcept
Definition: StringUtils.h:106
const char * begin(const char *str) noexcept
Definition: StringUtils.h:101
void copy(const T *src, T *dst, int32_t n)
Definition: VectorOps.h:40