1 | #pragma once |
---|---|
2 | |
3 | #include <vector> |
4 | |
5 | #include <IO/ReadBuffer.h> |
6 | |
7 | |
8 | namespace DB |
9 | { |
10 | |
11 | /** Reads from the concatenation of multiple ReadBuffers |
12 | */ |
13 | class ConcatReadBuffer : public ReadBuffer |
14 | { |
15 | public: |
16 | using ReadBuffers = std::vector<ReadBuffer *>; |
17 | |
18 | protected: |
19 | ReadBuffers buffers; |
20 | ReadBuffers::iterator current; |
21 | |
22 | bool nextImpl() override |
23 | { |
24 | if (buffers.end() == current) |
25 | return false; |
26 | |
27 | /// First reading |
28 | if (working_buffer.size() == 0 && (*current)->hasPendingData()) |
29 | { |
30 | working_buffer = Buffer((*current)->position(), (*current)->buffer().end()); |
31 | return true; |
32 | } |
33 | |
34 | if (!(*current)->next()) |
35 | { |
36 | ++current; |
37 | if (buffers.end() == current) |
38 | return false; |
39 | |
40 | /// We skip the filled up buffers; if the buffer is not filled in, but the cursor is at the end, then read the next piece of data. |
41 | while ((*current)->eof()) |
42 | { |
43 | ++current; |
44 | if (buffers.end() == current) |
45 | return false; |
46 | } |
47 | } |
48 | |
49 | working_buffer = Buffer((*current)->position(), (*current)->buffer().end()); |
50 | return true; |
51 | } |
52 | |
53 | public: |
54 | ConcatReadBuffer(const ReadBuffers & buffers_) : ReadBuffer(nullptr, 0), buffers(buffers_), current(buffers.begin()) {} |
55 | |
56 | ConcatReadBuffer(ReadBuffer & buf1, ReadBuffer & buf2) : ReadBuffer(nullptr, 0) |
57 | { |
58 | buffers.push_back(&buf1); |
59 | buffers.push_back(&buf2); |
60 | current = buffers.begin(); |
61 | } |
62 | }; |
63 | |
64 | } |
65 |