KTextEditor

linerange.h
1 /*
2  SPDX-FileCopyrightText: 2001-2005 Christoph Cullmann <[email protected]>
3  SPDX-FileCopyrightText: 2021 Dominik Haumann <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.0-or-later
6 */
7 
8 #ifndef KTEXTEDITOR_LINERANGE_H
9 #define KTEXTEDITOR_LINERANGE_H
10 
11 #include <ktexteditor_export.h>
12 
13 #include <QDebug>
14 #include <QtGlobal>
15 
16 namespace KTextEditor
17 {
18 /**
19  * @class LineRange linerange.h <KTextEditor/LineRange>
20  *
21  * @short An object representing lines from a start line to an end line.
22  *
23  * A LineRange is a basic class which represents a range of lines, from a start()
24  * line to an end() line.
25  *
26  * For simplicity and convenience, ranges always maintain their start() line to
27  * be before or equal to their end() line. Attempting to set either the
28  * start or end of the range beyond the respective end or start will result in
29  * both values being set to the specified line. In the constructor, the
30  * start and end will be swapped if necessary.
31  *
32  * @sa Range
33  *
34  * @since 5.79
35  * @author Dominik Haumann <[email protected]>
36  */
37 class KTEXTEDITOR_EXPORT LineRange
38 {
39 public:
40  /**
41  * Default constructor. Creates a valid line range with both start and end
42  * line set to 0.
43  */
44  Q_DECL_CONSTEXPR LineRange() Q_DECL_NOEXCEPT
45  {
46  }
47 
48  /**
49  * Constructor which creates a range from \e start to \e end.
50  * If start is after end, they will be swapped.
51  *
52  * @param start start line
53  * @param end end line
54  */
55  Q_DECL_CONSTEXPR LineRange(int start, int end) Q_DECL_NOEXCEPT : m_start(qMin(start, end)), m_end(qMax(start, end))
56  {
57  }
58 
59  /**
60  * Validity check. In the base class, returns true unless the line range starts before (0,0).
61  */
62  Q_DECL_CONSTEXPR inline bool isValid() const Q_DECL_NOEXCEPT
63  {
64  return m_start >= 0 && m_end >= 0;
65  }
66 
67  /**
68  * Returns an invalid line range.
69  */
70  Q_DECL_CONSTEXPR static LineRange invalid() Q_DECL_NOEXCEPT
71  {
72  return LineRange(-1, -1);
73  }
74 
75  /**
76  * Returns the line range as string in the format
77  * "[start line, end line]".
78  * @see fromString()
79  */
80  QString toString() const
81  {
82  return QLatin1Char('[') + QString::number(m_start) + QLatin1String(", ") + QString::number(m_end) + QLatin1Char(']');
83  }
84 
85  /**
86  * Returns a LineRange created from the string \p str containing the format
87  * "[start line, end line]".
88  * In case the string cannot be parsed, an LineRange::invalid() is returned.
89  * @see toString()
90  */
91  static LineRange fromString(QStringView str) Q_DECL_NOEXCEPT;
92 
93  /**
94  * @name Position
95  *
96  * The following functions provide access to, and manipulation of, the range's position.
97  * @{
98  */
99 
100  /**
101  * Get the start line of this line range. This will always be <= end().
102  *
103  * @returns the start line of this line range.
104  */
105  Q_DECL_CONSTEXPR inline int start() const Q_DECL_NOEXCEPT
106  {
107  return m_start;
108  }
109 
110  /**
111  * Get the end line of this line range. This will always be >= start().
112  *
113  * @returns the end line of this line range.
114  */
115  Q_DECL_CONSTEXPR inline int end() const Q_DECL_NOEXCEPT
116  {
117  return m_end;
118  }
119 
120  /**
121  * Set the start and end lines to \e start and \e end respectively.
122  *
123  * \note If \e start is after \e end, they will be reversed.
124  *
125  * \param start start line
126  * \param end end line
127  */
128  void setRange(const LineRange &range) Q_DECL_NOEXCEPT
129  {
130  setRange(range.start(), range.end());
131  }
132 
133  /**
134  * Set the start and end lines to \e start and \e end respectively.
135  *
136  * \note If \e start is after \e end, they will be reversed.
137  *
138  * \param start start line
139  * \param end end line
140  */
141  void setRange(int start, int end) Q_DECL_NOEXCEPT
142  {
143  m_start = qMin(start, end);
144  m_end = qMax(start, end);
145  }
146 
147  /**
148  * Convenience function. Set the start and end lines to \p line.
149  *
150  * @param line the line number to assign to start() and end()
151  */
152  void setBothLines(int line) Q_DECL_NOEXCEPT
153  {
154  m_start = line;
155  m_end = line;
156  }
157 
158  /**
159  * Set the start line to \e start.
160  *
161  * @note If \e start is after current end, start and end will be set to new start value.
162  *
163  * @param start new start line
164  */
165  inline void setStart(int start) Q_DECL_NOEXCEPT
166  {
167  if (start > end()) {
168  setRange(start, start);
169  } else {
170  setRange(start, end());
171  }
172  }
173 
174  /**
175  * Set the end line to \e end.
176  *
177  * @note If \e end is in front of current start, start and end will be set to new end value.
178  *
179  * @param end new end line
180  */
181  inline void setEnd(int end) Q_DECL_NOEXCEPT
182  {
183  if (end < start()) {
184  setRange(end, end);
185  } else {
186  setRange(start(), end);
187  }
188  }
189 
190  /**
191  * Expand this line range if necessary to contain \p range.
192  *
193  * @param range range which this range should contain
194  *
195  * @return \e true if expansion occurred, \e false otherwise
196  */
197  bool expandToRange(const LineRange &range) Q_DECL_NOEXCEPT
198  {
199  if (start() > range.start())
200  if (end() < range.end()) {
201  setRange(range);
202  } else {
203  setStart(range.start());
204  }
205  else if (end() < range.end()) {
206  setEnd(range.end());
207  } else {
208  return false;
209  }
210 
211  return true;
212  }
213 
214  /**
215  * Confine this range if necessary to fit within \p range.
216  *
217  * @param range range which should contain this range
218  *
219  * @return \e true if confinement occurred, \e false otherwise
220  */
221  bool confineToRange(const LineRange &range) Q_DECL_NOEXCEPT
222  {
223  if (start() < range.start())
224  if (end() > range.end()) {
225  setRange(range);
226  } else {
227  setStart(range.start());
228  }
229  else if (end() > range.end()) {
230  setEnd(range.end());
231  } else {
232  return false;
233  }
234 
235  return true;
236  }
237 
238  /**
239  * Check whether this line range is on one line.
240  *
241  * @return \e true if both the start and end line are equal, otherwise \e false
242  */
243  Q_DECL_CONSTEXPR inline bool onSingleLine() const Q_DECL_NOEXCEPT
244  {
245  return start() == end();
246  }
247 
248  /**
249  * Returns the number of lines separating the start() and end() line.
250  *
251  * @return the number of lines separating the start() and end() line;
252  * 0 if the start and end lines are the same.
253  */
254  Q_DECL_CONSTEXPR inline int numberOfLines() const Q_DECL_NOEXCEPT
255  {
256  return end() - start();
257  }
258 
259  // BEGIN comparison functions
260  /**
261  * @}
262  *
263  * @name Comparison
264  *
265  * The following functions perform checks against this range in comparison
266  * to other lines and ranges.
267  * @{
268  */
269  /**
270  * Check whether the this range wholly encompasses \e range.
271  *
272  * @param range range to check
273  *
274  * @return \e true, if this range contains \e range, otherwise \e false
275  */
276  Q_DECL_CONSTEXPR inline bool contains(const LineRange &range) const Q_DECL_NOEXCEPT
277  {
278  return range.start() >= start() && range.end() <= end();
279  }
280 
281  /**
282  * Returns true if this range wholly encompasses \p line.
283  *
284  * @param line line to check
285  *
286  * @return \e true if the line is wholly encompassed by this range, otherwise \e false.
287  */
288  Q_DECL_CONSTEXPR inline bool containsLine(int line) const Q_DECL_NOEXCEPT
289  {
290  return line >= start() && line < end();
291  }
292 
293  /**
294  * Check whether the this range overlaps with \e range.
295  *
296  * @param range range to check against
297  *
298  * @return \e true, if this range overlaps with \e range, otherwise \e false
299  */
300  Q_DECL_CONSTEXPR inline bool overlaps(const LineRange &range) const Q_DECL_NOEXCEPT
301  {
302  return (range.start() <= start()) ? (range.end() > start()) : (range.end() >= end()) ? (range.start() < end()) : contains(range);
303  }
304 
305  /**
306  * Check whether the range overlaps at least part of \e line.
307  *
308  * @param line line to check
309  *
310  * @return \e true, if the range overlaps at least part of \e line, otherwise \e false
311  */
312  Q_DECL_CONSTEXPR inline bool overlapsLine(int line) const Q_DECL_NOEXCEPT
313  {
314  return line >= start() && line <= end();
315  }
316  //!\}
317  // END
318 
319  /**
320  * Intersects this line range with another, returning the shared lines of
321  * the two line ranges.
322  *
323  * @param range other line range to intersect with this
324  *
325  * @return the intersection of this range and the supplied \a range.
326  */
327  Q_DECL_CONSTEXPR inline LineRange intersect(const LineRange &range) const Q_DECL_NOEXCEPT
328  {
329  return ((!isValid() || !range.isValid() || *this > range || *this < range)) ? invalid()
330  : LineRange(qMax(start(), range.start()), qMin(end(), range.end()));
331  }
332 
333  /**
334  * Returns the smallest range which encompasses this line range and the
335  * supplied \a range.
336  *
337  * @param range other range to encompass
338  *
339  * @return the smallest range which contains this range and the supplied \a range.
340  */
341  Q_DECL_CONSTEXPR inline LineRange encompass(const LineRange &range) const Q_DECL_NOEXCEPT
342  {
343  return (!isValid()) ? (range.isValid() ? range : invalid())
344  : (!range.isValid()) ? (*this) : LineRange(qMin(start(), range.start()), qMax(end(), range.end()));
345  }
346 
347  /**
348  * Addition operator. Takes two ranges and returns their summation.
349  *
350  * @param r1 the first range
351  * @param r2 the second range
352  *
353  * @return a the summation of the two input ranges
354  */
355  Q_DECL_CONSTEXPR inline friend LineRange operator+(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
356  {
357  return LineRange(r1.start() + r2.start(), r1.end() + r2.end());
358  }
359 
360  /**
361  * Addition assignment operator. Adds \p r2 to this range.
362  *
363  * @param r1 the first range
364  * @param r2 the second range
365  *
366  * @return a reference to the line range which has just been added to
367  */
368  inline friend LineRange &operator+=(LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
369  {
370  r1.setRange(r1.start() + r2.start(), r1.end() + r2.end());
371  return r1;
372  }
373 
374  /**
375  * Subtraction operator. Takes two ranges and returns the subtraction
376  * of \p r2 from \p r1.
377  *
378  * @param r1 the first range
379  * @param r2 the second range
380  *
381  * @return a range representing the subtraction of \p r2 from \p r1
382  */
383  Q_DECL_CONSTEXPR inline friend LineRange operator-(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
384  {
385  return LineRange(r1.start() - r2.start(), r1.end() - r2.end());
386  }
387 
388  /**
389  * Subtraction assignment operator. Subtracts \p r2 from \p r1.
390  *
391  * @param r1 the first range
392  * @param r2 the second range
393  *
394  * @return a reference to the range which has just been subtracted from
395  */
396  inline friend LineRange &operator-=(LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
397  {
398  r1.setRange(r1.start() - r2.start(), r1.end() - r2.end());
399  return r1;
400  }
401 
402  /**
403  * Intersects \a r1 and \a r2.
404  *
405  * @param r1 the first range
406  * @param r2 the second range
407  *
408  * @return the intersected range, invalid() if there is no overlap
409  */
410  Q_DECL_CONSTEXPR inline friend LineRange operator&(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
411  {
412  return r1.intersect(r2);
413  }
414 
415  /**
416  * Intersects \a r1 with \a r2 and assigns the result to \a r1.
417  *
418  * @param r1 the range to assign the intersection to
419  * @param r2 the range to intersect \a r1 with
420  *
421  * @return a reference to this range, after the intersection has taken place
422  */
423  inline friend LineRange &operator&=(LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
424  {
425  r1.setRange(r1.intersect(r2));
426  return r1;
427  }
428 
429  /**
430  * Equality operator.
431  *
432  * @param r1 first range to compare
433  * @param r2 second range to compare
434  *
435  * @return \e true if \e r1 and \e r2 equal, otherwise \e false
436  */
437  Q_DECL_CONSTEXPR inline friend bool operator==(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
438  {
439  return r1.start() == r2.start() && r1.end() == r2.end();
440  }
441 
442  /**
443  * Inequality operator.
444  *
445  * @param r1 first range to compare
446  * @param r2 second range to compare
447  *
448  * @return \e true if \e r1 and \e r2 do \e not equal, otherwise \e false
449  */
450  Q_DECL_CONSTEXPR inline friend bool operator!=(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
451  {
452  return r1.start() != r2.start() || r1.end() != r2.end();
453  }
454 
455  /**
456  * Greater than operator. Looks only at the lines of the two ranges,
457  * does not consider their size.
458  *
459  * @param r1 first range to compare
460  * @param r2 second range to compare
461  *
462  * @return \e true if \e r1 starts after where \e r2 ends, otherwise \e false
463  */
464  Q_DECL_CONSTEXPR inline friend bool operator>(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
465  {
466  return r1.start() > r2.end();
467  }
468 
469  /**
470  * Less than operator. Looks only at the lines of the two ranges,
471  * does not consider their size.
472  *
473  * @param r1 first range to compare
474  * @param r2 second range to compare
475  *
476  * @return \e true if \e r1 ends before \e r2 begins, otherwise \e false
477  */
478  Q_DECL_CONSTEXPR inline friend bool operator<(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
479  {
480  return r1.end() < r2.start();
481  }
482 
483  /**
484  * qDebug() stream operator. Writes this range to the debug output in a nicely formatted way.
485  */
486  inline friend QDebug operator<<(QDebug s, const LineRange &range)
487  {
488  s << "[" << range.start() << " -> " << range.end() << "]";
489  return s;
490  }
491 
492 private:
493  /**
494  * This range's start line.
495  *
496  * @internal
497  */
498  int m_start = 0;
499 
500  /**
501  * This range's end line.
502  *
503  * @internal
504  */
505  int m_end = 0;
506 };
507 
508 }
509 
510 Q_DECLARE_TYPEINFO(KTextEditor::LineRange, Q_MOVABLE_TYPE);
511 Q_DECLARE_METATYPE(KTextEditor::LineRange)
512 
513 /**
514  * QHash function for KTextEditor::LineRange.
515  * Returns the hash value for @p range.
516  */
517 inline uint qHash(const KTextEditor::LineRange &range, uint seed = 0) Q_DECL_NOTHROW
518 {
519  return qHash(qMakePair(qHash(range.start()), qHash(range.end())), seed);
520 }
521 
522 namespace QTest
523 {
524 // forward declaration of template in qtestcase.h
525 template<typename T>
526 char *toString(const T &);
527 
528 /**
529  * QTestLib integration to have nice output in e.g. QCOMPARE failures.
530  */
531 template<>
532 KTEXTEDITOR_EXPORT char *toString(const KTextEditor::LineRange &range);
533 }
534 
535 #endif
constexpr int end() const Q_DECL_NOEXCEPT
Get the end line of this line range.
Definition: linerange.h:115
constexpr bool overlapsLine(int line) const Q_DECL_NOEXCEPT
Check whether the range overlaps at least part of line.
Definition: linerange.h:312
friend LineRange & operator-=(LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Subtraction assignment operator.
Definition: linerange.h:396
friend LineRange & operator+=(LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Addition assignment operator.
Definition: linerange.h:368
friend QDebug operator<<(QDebug s, const LineRange &range)
qDebug() stream operator.
Definition: linerange.h:486
bool expandToRange(const LineRange &range) Q_DECL_NOEXCEPT
Expand this line range if necessary to contain range.
Definition: linerange.h:197
static constexpr LineRange invalid() Q_DECL_NOEXCEPT
Returns an invalid line range.
Definition: linerange.h:70
constexpr LineRange() Q_DECL_NOEXCEPT
Default constructor.
Definition: linerange.h:44
constexpr bool overlaps(const LineRange &range) const Q_DECL_NOEXCEPT
Check whether the this range overlaps with range.
Definition: linerange.h:300
constexpr friend bool operator==(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Equality operator.
Definition: linerange.h:437
constexpr bool isValid() const Q_DECL_NOEXCEPT
Validity check.
Definition: linerange.h:62
constexpr friend LineRange operator-(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Subtraction operator.
Definition: linerange.h:383
constexpr LineRange(int start, int end) Q_DECL_NOEXCEPT
Constructor which creates a range from start to end.
Definition: linerange.h:55
QString toString() const
Returns the line range as string in the format "[start line, end line]".
Definition: linerange.h:80
QString number(int n, int base)
constexpr friend bool operator!=(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Inequality operator.
Definition: linerange.h:450
An object representing lines from a start line to an end line.
Definition: linerange.h:37
constexpr LineRange intersect(const LineRange &range) const Q_DECL_NOEXCEPT
Intersects this line range with another, returning the shared lines of the two line ranges...
Definition: linerange.h:327
void setStart(int start) Q_DECL_NOEXCEPT
Set the start line to start.
Definition: linerange.h:165
constexpr LineRange encompass(const LineRange &range) const Q_DECL_NOEXCEPT
Returns the smallest range which encompasses this line range and the supplied range.
Definition: linerange.h:341
constexpr friend LineRange operator&(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Intersects r1 and r2.
Definition: linerange.h:410
constexpr bool containsLine(int line) const Q_DECL_NOEXCEPT
Returns true if this range wholly encompasses line.
Definition: linerange.h:288
The KTextEditor namespace contains all the public API that is required to use the KTextEditor compone...
Definition: katetextblock.h:20
constexpr friend LineRange operator+(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Addition operator.
Definition: linerange.h:355
KCALENDARCORE_EXPORT uint qHash(const KCalendarCore::Period &key)
void setEnd(int end) Q_DECL_NOEXCEPT
Set the end line to end.
Definition: linerange.h:181
friend LineRange & operator&=(LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Intersects r1 with r2 and assigns the result to r1.
Definition: linerange.h:423
void setRange(int start, int end) Q_DECL_NOEXCEPT
Set the start and end lines to start and end respectively.
Definition: linerange.h:141
bool confineToRange(const LineRange &range) Q_DECL_NOEXCEPT
Confine this range if necessary to fit within range.
Definition: linerange.h:221
constexpr int start() const Q_DECL_NOEXCEPT
Get the start line of this line range.
Definition: linerange.h:105
constexpr int numberOfLines() const Q_DECL_NOEXCEPT
Returns the number of lines separating the start() and end() line.
Definition: linerange.h:254
void setBothLines(int line) Q_DECL_NOEXCEPT
Convenience function.
Definition: linerange.h:152
constexpr bool contains(const LineRange &range) const Q_DECL_NOEXCEPT
Check whether the this range wholly encompasses range.
Definition: linerange.h:276
constexpr bool onSingleLine() const Q_DECL_NOEXCEPT
Check whether this line range is on one line.
Definition: linerange.h:243
constexpr friend bool operator>(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Greater than operator.
Definition: linerange.h:464
constexpr friend bool operator<(const LineRange &r1, const LineRange &r2) Q_DECL_NOEXCEPT
Less than operator.
Definition: linerange.h:478
void setRange(const LineRange &range) Q_DECL_NOEXCEPT
Set the start and end lines to start and end respectively.
Definition: linerange.h:128
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Tue Jul 27 2021 22:58:00 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.