| 1 | #pragma once |
| 2 | |
| 3 | #include <IO/ReadBuffer.h> |
| 4 | #include <IO/WriteBuffer.h> |
| 5 | #include <IO/ReadHelpers.h> |
| 6 | #include <IO/WriteHelpers.h> |
| 7 | |
| 8 | #include <functional> |
| 9 | |
| 10 | |
| 11 | namespace DB |
| 12 | { |
| 13 | |
| 14 | /** Implements the ability to write and read data in/from WriteBuffer/ReadBuffer |
| 15 | * with the help of << and >> operators and also manipulators, |
| 16 | * providing a way of using, similar to iostreams. |
| 17 | * |
| 18 | * It is neither a subset nor an extension of iostreams. |
| 19 | * |
| 20 | * Example usage: |
| 21 | * |
| 22 | * DB::WriteBufferFromFileDescriptor buf(STDOUT_FILENO); |
| 23 | * buf << DB::double_quote << "Hello, world!" << '\n' << DB::flush; |
| 24 | * |
| 25 | * Outputs `char` type (usually it's Int8) as a symbol, not as a number. |
| 26 | */ |
| 27 | |
| 28 | /// Manipulators. |
| 29 | enum EscapeManip { escape }; /// For strings - escape special characters. In the rest, as usual. |
| 30 | enum QuoteManip { quote }; /// For strings, dates, datetimes - enclose in single quotes with escaping. In the rest, as usual. |
| 31 | enum DoubleQuoteManip { double_quote }; /// For strings, dates, datetimes - enclose in double quotes with escaping. In the rest, as usual. |
| 32 | enum BinaryManip { binary }; /// Output in binary format. |
| 33 | |
| 34 | struct EscapeManipWriteBuffer : std::reference_wrapper<WriteBuffer> { using std::reference_wrapper<WriteBuffer>::reference_wrapper; }; |
| 35 | struct QuoteManipWriteBuffer : std::reference_wrapper<WriteBuffer> { using std::reference_wrapper<WriteBuffer>::reference_wrapper; }; |
| 36 | struct DoubleQuoteManipWriteBuffer : std::reference_wrapper<WriteBuffer> { using std::reference_wrapper<WriteBuffer>::reference_wrapper; }; |
| 37 | struct BinaryManipWriteBuffer : std::reference_wrapper<WriteBuffer> { using std::reference_wrapper<WriteBuffer>::reference_wrapper; }; |
| 38 | |
| 39 | struct EscapeManipReadBuffer : std::reference_wrapper<ReadBuffer> { using std::reference_wrapper<ReadBuffer>::reference_wrapper; }; |
| 40 | struct QuoteManipReadBuffer : std::reference_wrapper<ReadBuffer> { using std::reference_wrapper<ReadBuffer>::reference_wrapper; }; |
| 41 | struct DoubleQuoteManipReadBuffer : std::reference_wrapper<ReadBuffer> { using std::reference_wrapper<ReadBuffer>::reference_wrapper; }; |
| 42 | struct BinaryManipReadBuffer : std::reference_wrapper<ReadBuffer> { using std::reference_wrapper<ReadBuffer>::reference_wrapper; }; |
| 43 | |
| 44 | |
| 45 | template <typename T> WriteBuffer & operator<< (WriteBuffer & buf, const T & x) { writeText(x, buf); return buf; } |
| 46 | /// If you do not use the manipulators, the string is displayed without an escape, as is. |
| 47 | template <> inline WriteBuffer & operator<< (WriteBuffer & buf, const String & x) { writeString(x, buf); return buf; } |
| 48 | template <> inline WriteBuffer & operator<< (WriteBuffer & buf, const char & x) { writeChar(x, buf); return buf; } |
| 49 | |
| 50 | inline WriteBuffer & operator<< (WriteBuffer & buf, const char * x) { writeCString(x, buf); return buf; } |
| 51 | |
| 52 | inline EscapeManipWriteBuffer operator<< (WriteBuffer & buf, EscapeManip) { return buf; } |
| 53 | inline QuoteManipWriteBuffer operator<< (WriteBuffer & buf, QuoteManip) { return buf; } |
| 54 | inline DoubleQuoteManipWriteBuffer operator<< (WriteBuffer & buf, DoubleQuoteManip) { return buf; } |
| 55 | inline BinaryManipWriteBuffer operator<< (WriteBuffer & buf, BinaryManip) { return buf; } |
| 56 | |
| 57 | template <typename T> WriteBuffer & operator<< (EscapeManipWriteBuffer buf, const T & x) { writeText(x, buf.get()); return buf; } |
| 58 | template <typename T> WriteBuffer & operator<< (QuoteManipWriteBuffer buf, const T & x) { writeQuoted(x, buf.get()); return buf; } |
| 59 | template <typename T> WriteBuffer & operator<< (DoubleQuoteManipWriteBuffer buf, const T & x) { writeDoubleQuoted(x, buf.get()); return buf; } |
| 60 | template <typename T> WriteBuffer & operator<< (BinaryManipWriteBuffer buf, const T & x) { writeBinary(x, buf.get()); return buf; } |
| 61 | |
| 62 | inline WriteBuffer & operator<< (EscapeManipWriteBuffer buf, const char * x) { writeAnyEscapedString<'\''>(x, x + strlen(x), buf.get()); return buf; } |
| 63 | inline WriteBuffer & operator<< (QuoteManipWriteBuffer buf, const char * x) { writeAnyQuotedString<'\''>(x, x + strlen(x), buf.get()); return buf; } |
| 64 | inline WriteBuffer & operator<< (DoubleQuoteManipWriteBuffer buf, const char * x) { writeAnyQuotedString<'"'>(x, x + strlen(x), buf.get()); return buf; } |
| 65 | inline WriteBuffer & operator<< (BinaryManipWriteBuffer buf, const char * x) { writeStringBinary(x, buf.get()); return buf; } |
| 66 | |
| 67 | /// The manipulator calls the WriteBuffer method `next` - this makes the buffer reset. For nested buffers, the reset is not recursive. |
| 68 | enum FlushManip { flush }; |
| 69 | |
| 70 | inline WriteBuffer & operator<< (WriteBuffer & buf, FlushManip) { buf.next(); return buf; } |
| 71 | |
| 72 | |
| 73 | template <typename T> ReadBuffer & operator>> (ReadBuffer & buf, T & x) { readText(x, buf); return buf; } |
| 74 | template <> inline ReadBuffer & operator>> (ReadBuffer & buf, String & x) { readString(x, buf); return buf; } |
| 75 | template <> inline ReadBuffer & operator>> (ReadBuffer & buf, char & x) { readChar(x, buf); return buf; } |
| 76 | |
| 77 | /// If you specify a string literal for reading, this will mean - make sure there is a sequence of bytes and skip it. |
| 78 | inline ReadBuffer & operator>> (ReadBuffer & buf, const char * x) { assertString(x, buf); return buf; } |
| 79 | |
| 80 | inline EscapeManipReadBuffer operator>> (ReadBuffer & buf, EscapeManip) { return buf; } |
| 81 | inline QuoteManipReadBuffer operator>> (ReadBuffer & buf, QuoteManip) { return buf; } |
| 82 | inline DoubleQuoteManipReadBuffer operator>> (ReadBuffer & buf, DoubleQuoteManip) { return buf; } |
| 83 | inline BinaryManipReadBuffer operator>> (ReadBuffer & buf, BinaryManip) { return buf; } |
| 84 | |
| 85 | template <typename T> ReadBuffer & operator>> (EscapeManipReadBuffer buf, T & x) { readText(x, buf.get()); return buf; } |
| 86 | template <typename T> ReadBuffer & operator>> (QuoteManipReadBuffer buf, T & x) { readQuoted(x, buf.get()); return buf; } |
| 87 | template <typename T> ReadBuffer & operator>> (DoubleQuoteManipReadBuffer buf, T & x) { readDoubleQuoted(x, buf.get()); return buf; } |
| 88 | template <typename T> ReadBuffer & operator>> (BinaryManipReadBuffer buf, T & x) { readBinary(x, buf.get()); return buf; } |
| 89 | |
| 90 | } |
| 91 | |