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
20using namespace KTextEditor;
21
22Range 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
35void Range::setRange(Range range) noexcept
36{
37 m_start = range.start();
38 m_end = range.end();
39}
40
41void 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
50bool 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
67bool 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
84void Range::setBothLines(int line) noexcept
85{
86 setRange(Range(line, start().column(), line, end().column()));
87}
88
89void KTextEditor::Range::setBothColumns(int column) noexcept
90{
91 setRange(Range(start().line(), column, end().line(), column));
92}
93
94LineRange 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
118QDebug operator<<(QDebug s, KTextEditor::Range range)
119{
120 s << "[" << range.start() << " -> " << range.end() << "]";
121 return s;
122}
123
124QDebug operator<<(QDebug s, KTextEditor::LineRange range)
125{
126 s << "[" << range.start() << " -> " << range.end() << "]";
127 return s;
128}
129
130size_t KTextEditor::qHash(KTextEditor::LineRange range, size_t seed) noexcept
131{
132 return qHashMulti(seed, args: range.start(), args: range.end());
133}
134
135size_t KTextEditor::qHash(KTextEditor::Range range, size_t seed) noexcept
136{
137 return qHashMulti(seed, args: range.start(), args: range.end());
138}
139
140QString Range::toString() const
141{
142 return QStringLiteral("[%1, %2]").arg(a: m_start.toString()).arg(a: m_end.toString());
143}
144
145QString LineRange::toString() const
146{
147 return QStringLiteral("[%1, %2]").arg(a: m_start).arg(a: m_end);
148}
149
150namespace QTest
151{
152// Cursor: template specialization for QTest::toString()
153template<>
154char *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()
161template<>
162char *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()
172template<>
173char *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

source code of ktexteditor/src/utils/range.cpp