1 | /* |
2 | SPDX-FileCopyrightText: 2016 Dominik Haumann <dhaumann@kde.org> |
3 | SPDX-FileCopyrightText: 2007 Mirko Stocker <me@misto.ch> |
4 | SPDX-FileCopyrightText: 2003-2005 Hamish Rodda <rodda@kde.org> |
5 | SPDX-FileCopyrightText: 2002 Christian Couder <christian@kdevelop.org> |
6 | SPDX-FileCopyrightText: 2001, 2003 Christoph Cullmann <cullmann@kde.org> |
7 | SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org> |
8 | SPDX-FileCopyrightText: 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de> |
9 | |
10 | SPDX-License-Identifier: LGPL-2.0-or-later |
11 | */ |
12 | |
13 | #include "range.h" |
14 | |
15 | #include <QByteArray> |
16 | #include <QDebug> |
17 | #include <QHash> |
18 | #include <QString> |
19 | |
20 | using namespace KTextEditor; |
21 | |
22 | Range Range::fromString(QStringView str) noexcept |
23 | { |
24 | const int startIndex = str.indexOf(c: QLatin1Char('[')); |
25 | const int endIndex = str.indexOf(c: QLatin1Char(']')); |
26 | const int closeIndex = str.indexOf(c: QLatin1Char(')')); // end of first cursor |
27 | |
28 | if (startIndex < 0 || endIndex < 0 || closeIndex < 0 || closeIndex < startIndex || endIndex < closeIndex || endIndex < startIndex) { |
29 | return invalid(); |
30 | } |
31 | |
32 | return Range(Cursor::fromString(str: str.mid(pos: startIndex + 1, n: closeIndex - startIndex)), Cursor::fromString(str: str.mid(pos: closeIndex + 2, n: endIndex - closeIndex - 2))); |
33 | } |
34 | |
35 | void Range::setRange(Range range) noexcept |
36 | { |
37 | m_start = range.start(); |
38 | m_end = range.end(); |
39 | } |
40 | |
41 | void Range::setRange(Cursor start, Cursor end) noexcept |
42 | { |
43 | if (start > end) { |
44 | setRange(Range(end, start)); |
45 | } else { |
46 | setRange(Range(start, end)); |
47 | } |
48 | } |
49 | |
50 | bool Range::confineToRange(Range range) noexcept |
51 | { |
52 | if (start() < range.start()) { |
53 | if (end() > range.end()) { |
54 | setRange(range); |
55 | } else { |
56 | setStart(range.start()); |
57 | } |
58 | } else if (end() > range.end()) { |
59 | setEnd(range.end()); |
60 | } else { |
61 | return false; |
62 | } |
63 | |
64 | return true; |
65 | } |
66 | |
67 | bool Range::expandToRange(Range range) noexcept |
68 | { |
69 | if (start() > range.start()) { |
70 | if (end() < range.end()) { |
71 | setRange(range); |
72 | } else { |
73 | setStart(range.start()); |
74 | } |
75 | } else if (end() < range.end()) { |
76 | setEnd(range.end()); |
77 | } else { |
78 | return false; |
79 | } |
80 | |
81 | return true; |
82 | } |
83 | |
84 | void Range::setBothLines(int line) noexcept |
85 | { |
86 | setRange(Range(line, start().column(), line, end().column())); |
87 | } |
88 | |
89 | void KTextEditor::Range::setBothColumns(int column) noexcept |
90 | { |
91 | setRange(Range(start().line(), column, end().line(), column)); |
92 | } |
93 | |
94 | LineRange LineRange::fromString(QStringView str) noexcept |
95 | { |
96 | // parse format "[start, end]" |
97 | const int startIndex = str.indexOf(c: QLatin1Char('[')); |
98 | const int endIndex = str.indexOf(c: QLatin1Char(']')); |
99 | const int commaIndex = str.indexOf(c: QLatin1Char(',')); |
100 | |
101 | if (startIndex < 0 || endIndex < 0 || commaIndex < 0 || commaIndex < startIndex || endIndex < commaIndex || endIndex < startIndex) { |
102 | return invalid(); |
103 | } |
104 | |
105 | bool ok1 = false; |
106 | bool ok2 = false; |
107 | |
108 | const int start = str.mid(pos: startIndex + 1, n: commaIndex - startIndex - 1).toInt(ok: &ok1); |
109 | const int end = str.mid(pos: commaIndex + 1, n: endIndex - commaIndex - 1).toInt(ok: &ok2); |
110 | |
111 | if (!ok1 || !ok2) { |
112 | return invalid(); |
113 | } |
114 | |
115 | return {start, end}; |
116 | } |
117 | |
118 | QDebug operator<<(QDebug s, KTextEditor::Range range) |
119 | { |
120 | s << "[" << range.start() << " -> " << range.end() << "]" ; |
121 | return s; |
122 | } |
123 | |
124 | QDebug operator<<(QDebug s, KTextEditor::LineRange range) |
125 | { |
126 | s << "[" << range.start() << " -> " << range.end() << "]" ; |
127 | return s; |
128 | } |
129 | |
130 | size_t KTextEditor::qHash(KTextEditor::LineRange range, size_t seed) noexcept |
131 | { |
132 | return qHashMulti(seed, args: range.start(), args: range.end()); |
133 | } |
134 | |
135 | size_t KTextEditor::qHash(KTextEditor::Range range, size_t seed) noexcept |
136 | { |
137 | return qHashMulti(seed, args: range.start(), args: range.end()); |
138 | } |
139 | |
140 | QString Range::toString() const |
141 | { |
142 | return QStringLiteral("[%1, %2]" ).arg(a: m_start.toString()).arg(a: m_end.toString()); |
143 | } |
144 | |
145 | QString LineRange::toString() const |
146 | { |
147 | return QStringLiteral("[%1, %2]" ).arg(a: m_start).arg(a: m_end); |
148 | } |
149 | |
150 | namespace QTest |
151 | { |
152 | // Cursor: template specialization for QTest::toString() |
153 | template<> |
154 | char *toString(const KTextEditor::Cursor &cursor) |
155 | { |
156 | QByteArray ba = "Cursor[" + QByteArray::number(cursor.line()) + ", " + QByteArray::number(cursor.column()) + ']'; |
157 | return qstrdup(ba.data()); |
158 | } |
159 | |
160 | // Range: template specialization for QTest::toString() |
161 | template<> |
162 | char *toString(const KTextEditor::Range &range) |
163 | { |
164 | QByteArray ba = "Range[" ; |
165 | ba += QByteArray::number(range.start().line()) + ", " + QByteArray::number(range.start().column()) + " - " ; |
166 | ba += QByteArray::number(range.end().line()) + ", " + QByteArray::number(range.end().column()); |
167 | ba += ']'; |
168 | return qstrdup(ba.data()); |
169 | } |
170 | |
171 | // LineRange: template specialization for QTest::toString() |
172 | template<> |
173 | char *toString(const KTextEditor::LineRange &range) |
174 | { |
175 | QByteArray ba = "LineRange[" ; |
176 | ba += QByteArray::number(range.start()) + ", " + QByteArray::number(range.end()); |
177 | ba += ']'; |
178 | return qstrdup(ba.data()); |
179 | } |
180 | } |
181 | |