1 | // Copyright (C) 2020 The Qt Company Ltd. |
2 | // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only |
3 | |
4 | #ifndef DUMPER_H |
5 | #define DUMPER_H |
6 | |
7 | // |
8 | // W A R N I N G |
9 | // ------------- |
10 | // |
11 | // This file is not part of the Qt API. It exists purely as an |
12 | // implementation detail. This header file may change from version to |
13 | // version without notice, or even be removed. |
14 | // |
15 | // We mean it. |
16 | // |
17 | |
18 | #include "qqmldom_global.h" |
19 | #include "qqmldomconstants_p.h" |
20 | #include "qqmldomfunctionref_p.h" |
21 | |
22 | #include <QtCore/QString> |
23 | #include <QtCore/QStringView> |
24 | #include <QtCore/QDebug> |
25 | |
26 | #include <type_traits> |
27 | |
28 | QT_BEGIN_NAMESPACE |
29 | |
30 | namespace QQmlJS { |
31 | namespace Dom { |
32 | |
33 | using Sink = function_ref<void(QStringView)>; |
34 | using SinkF = std::function<void(QStringView)>; |
35 | using DumperFunction = std::function<void(Sink)>; |
36 | |
37 | class Dumper{ |
38 | public: |
39 | DumperFunction dumper; |
40 | private: |
41 | // We want to avoid the limit of one user conversion: |
42 | // after doing (* -> QStringView) we cannot have QStringView -> Dumper, as it |
43 | // would be the second user defined conversion. |
44 | // For a similar reason we have a template to accept function_ref<void(Sink)> . |
45 | // The end result is that void f(Dumper) can be called nicely, and avoid overloads: |
46 | // f(u"bla"), f(QLatin1String("bla")), f(QString()), f([](Sink s){...}),... |
47 | template <typename T> |
48 | using if_compatible_dumper = typename |
49 | std::enable_if<std::is_convertible<T, DumperFunction>::value, bool>::type; |
50 | |
51 | template<typename T> |
52 | using if_string_view_convertible = typename |
53 | std::enable_if<std::is_convertible_v<T, QStringView>, bool>::type; |
54 | |
55 | public: |
56 | Dumper(QStringView s): |
57 | dumper([s](Sink sink){ sink(s); }) {} |
58 | |
59 | Dumper(std::nullptr_t): Dumper(QStringView(nullptr)) {} |
60 | |
61 | template <typename Stringy, if_string_view_convertible<Stringy> = true> |
62 | Dumper(Stringy string): |
63 | Dumper(QStringView(string)) {} |
64 | |
65 | template <typename U, if_compatible_dumper<U> = true> |
66 | Dumper(U f): dumper(f) {} |
67 | |
68 | void operator()(Sink s) { dumper(s); } |
69 | }; |
70 | |
71 | template <typename T> |
72 | void sinkInt(Sink s, T i) { |
73 | const int BUFSIZE = 42; // safe up to 128 bits |
74 | QChar buf[BUFSIZE]; |
75 | int ibuf = BUFSIZE; |
76 | buf[--ibuf] = QChar(0); |
77 | bool neg = false; |
78 | if (i < 0) |
79 | neg=true; |
80 | int digit = i % 10; |
81 | i = i / 10; |
82 | if constexpr (std::is_signed_v<T>) { |
83 | if (neg) { // we change the sign here because -numeric_limits<T>::min() == numeric_limits<T>::min() |
84 | i = -i; |
85 | digit = - digit; |
86 | } |
87 | } |
88 | buf[--ibuf] = QChar::fromLatin1(c: '0' + digit); |
89 | while (i > 0 && ibuf > 0) { |
90 | digit = i % 10; |
91 | buf[--ibuf] = QChar::fromLatin1(c: '0' + digit); |
92 | i = i / 10; |
93 | } |
94 | if (neg && ibuf > 0) |
95 | buf[--ibuf] = QChar::fromLatin1(c: '-'); |
96 | s(QStringView(&buf[ibuf], BUFSIZE - ibuf -1)); |
97 | } |
98 | |
99 | QMLDOM_EXPORT QString dumperToString(Dumper writer); |
100 | |
101 | QMLDOM_EXPORT void sinkEscaped(Sink sink, QStringView s, |
102 | EscapeOptions options = EscapeOptions::OuterQuotes); |
103 | |
104 | inline void devNull(QStringView) {} |
105 | |
106 | QMLDOM_EXPORT void sinkIndent(Sink s, int indent); |
107 | |
108 | QMLDOM_EXPORT void sinkNewline(Sink s, int indent = 0); |
109 | |
110 | QMLDOM_EXPORT void dumpErrorLevel(Sink s, ErrorLevel level); |
111 | |
112 | QMLDOM_EXPORT void dumperToQDebug(Dumper dumper, QDebug debug); |
113 | |
114 | QMLDOM_EXPORT void dumperToQDebug(Dumper dumper, ErrorLevel level = ErrorLevel::Debug); |
115 | |
116 | QMLDOM_EXPORT QDebug operator<<(QDebug d, Dumper dumper); |
117 | |
118 | } // end namespace Dom |
119 | } // end namespace QQmlJS |
120 | QT_END_NAMESPACE |
121 | |
122 | #endif // DUMPER_H |
123 | |