diff options
Diffstat (limited to 'sources/shiboken6/ApiExtractor/textstream.h')
-rw-r--r-- | sources/shiboken6/ApiExtractor/textstream.h | 227 |
1 files changed, 227 insertions, 0 deletions
diff --git a/sources/shiboken6/ApiExtractor/textstream.h b/sources/shiboken6/ApiExtractor/textstream.h new file mode 100644 index 000000000..228f36405 --- /dev/null +++ b/sources/shiboken6/ApiExtractor/textstream.h @@ -0,0 +1,227 @@ +// Copyright (C) 2020 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#ifndef TEXTSTREAM_H +#define TEXTSTREAM_H + +#include <QtCore/QTextStream> +#include <QtCore/QString> + +/// A text stream based on QTextStream with built-in indent. +class TextStream +{ +public: + Q_DISABLE_COPY_MOVE(TextStream) + + using ManipulatorFunc = void(TextStream &); + + enum class Language + { + None, Cpp + }; + + enum class CharClass + { + Other, NewLine, Space, Hash, BackSlash + }; + + explicit TextStream(QIODevice *device, Language l = Language::None); + explicit TextStream(QString *string, Language l = Language::None); + explicit TextStream(QByteArray *array, Language l = Language::None); + virtual ~TextStream(); + + Language language() const { return m_language; } + void setLanguage(Language language) { m_language = language; } + + bool isIndentationEnabled() const { return m_indentationEnabled; } + void setIndentationEnabled(bool m) + { m_indentationEnabled = m; } + + int tabWidth() const { return m_tabWidth; } + void setTabWidth(int tabWidth) { m_tabWidth = tabWidth; } + + void setFieldWidth(int f) { m_str.setFieldWidth(f); } + int fieldWidth() const { return m_str.fieldWidth(); } + + int indentation() const { return m_indentation; } + void setIndentation(int i); + + void indent(int n = 1) { m_indentation += n; } + void outdent(int n = 1); + + // QTextStream API + qint64 pos() const; + QTextStream::FieldAlignment fieldAlignment() const + { return m_str.fieldAlignment(); } + void setFieldAlignment(QTextStream::FieldAlignment al) + { m_str.setFieldAlignment(al); } + void setString(QString *string, QIODeviceBase::OpenMode openMode = QIODeviceBase::ReadWrite); + QString *string() const { return m_str.string(); } + void flush() { m_str.flush(); } + void setDevice(QIODevice *device) { m_str.setDevice(device); } + QIODevice *device() const { return m_str.device(); } + QTextStream &textStream() { return m_str; } + + // Last character written, works only for streams on strings + QChar lastChar() const; + + void putString(QStringView v); + void putChar(QChar c); + void putString(const char *s); + void putChar(char c); + + void putInt(int t); + void putSizeType(qsizetype t); + + void putRawString(const char *s) { m_str << s; } + void putRawChar(char c) { m_str << c; } + + TextStream &operator<<(QStringView v) { putString(v); return *this; } + TextStream &operator<<(const QString &qs) { putString(QStringView{qs}); return *this; } + TextStream &operator<<(QLatin1StringView lv) { putString(lv.constData()); return *this; } + TextStream &operator<<(QUtf8StringView uv) { putString(uv.data()); return *this; } + TextStream &operator<<(const QByteArray &ba) { putString(ba.constData()); return *this; } + TextStream &operator<<(QChar c) { putChar(c); return *this; } + TextStream &operator<<(const char *s) { putString(s); return *this; } + TextStream &operator<<(char c) { putChar(c); return *this; } + TextStream &operator<<(int t) { putInt(t); return *this; } +#if QT_POINTER_SIZE != 4 + TextStream &operator<<(qsizetype t) { putSizeType(t); return *this; } +#endif + + inline TextStream &operator<<(const QTextStreamManipulator &m) { m_str << m; return *this; } + inline TextStream &operator<<(ManipulatorFunc f) { f(*this); return *this; } + + void putRepetitiveChars(char c, int count); + + void _setRstFormattingEnd(); + +protected: + void setLastCharClass(CharClass c); + +private: + void writeIndent(); + void checkIndent(CharClass upComingCharClass); + template <class Char> + void putCharHelper(Char c); + + QTextStream m_str; + CharClass m_lastCharClass = CharClass::NewLine; + int m_tabWidth = 4; + int m_indentation = 0; + bool m_indentationEnabled = true; + bool m_rstFormattingEnd = false; // just past some **bla** where '\' needs to be enforced + Language m_language; +}; + +/// Stream into a string (cf std::ostringstream) +class StringStream : public TextStream +{ +public: + StringStream(Language l = Language::None); + + qsizetype size() const { return m_buffer.size(); } + void clear(); + + const QString &toString() const { return m_buffer; } + operator const QString &() const { return m_buffer; } + +private: + QString m_buffer; +}; + +void indent(TextStream &s); +void outdent(TextStream &s); +void enableIndent(TextStream &s); +void disableIndent(TextStream &s); +// Works only for streams on strings +void ensureEndl(TextStream &s); + +void rstBold(TextStream &s); +void rstBoldOff(TextStream &s); +void rstCode(TextStream &s); +void rstCodeOff(TextStream &s); +void rstItalic(TextStream &s); +void rstItalicOff(TextStream &s); + +inline TextStream &operator<<(TextStream &str, QAnyStringView asv) +{ + asv.visit([&str](auto s) { str << s; }); + return str; +} + +/// Format an aligned field +template <class T> +class AlignedField +{ +public: + explicit AlignedField(T value, int fieldWidth, + QTextStream::FieldAlignment a = QTextStream::AlignLeft) : + m_value(value), m_fieldWidth(fieldWidth), m_alignment(a) + { + } + + void put(TextStream &s) const + { + const int oldFieldWidth = s.fieldWidth(); + const auto oldFieldAlignment = s.fieldAlignment(); + s.setFieldWidth(m_fieldWidth); + s.setFieldAlignment(m_alignment); + const auto oldPos = s.pos(); + s << m_value; + // Ensure something is written when an empty string is encountered + if (oldPos == s.pos() && m_fieldWidth > 0) + s << ' '; + s.setFieldAlignment(oldFieldAlignment); + s.setFieldWidth(oldFieldWidth); + } + +private: + const T m_value; + const int m_fieldWidth; + const QTextStream::FieldAlignment m_alignment; +}; + +template <class T> +TextStream &operator<<(TextStream &str, const AlignedField<T> &fa) +{ + fa.put(str); + return str; +} + +class Pad +{ +public: + explicit Pad(char c, int count) : m_char(c), m_count(count) {} + + void write(TextStream &str) const + { + for (int i = 0; i < m_count; ++i) + str << m_char; + } + +private: + const char m_char; + const int m_count; +}; + +inline TextStream &operator<<(TextStream &str, const Pad &pad) +{ + pad.write(str); + return str; +} + +class Indentation +{ +public: + Q_DISABLE_COPY_MOVE(Indentation) + + Indentation(TextStream &s, int n = 1) : m_s(s), m_n(n) { m_s.indent(m_n); } + ~Indentation() { m_s.outdent(m_n); } + +private: + TextStream &m_s; + const int m_n; +}; + +#endif // TEXTSTREAM_H |