File indexing completed on 2024-10-13 13:23:38
0001 // clang-format off 0002 /* 0003 * KDiff3 - Text Diff And Merge Tool 0004 * 0005 * SPDX-FileCopyrightText: 2018-2020 Michael Reeves reeves.87@gmail.com 0006 * SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 // clang-format on 0009 #ifndef LINEREF_H 0010 #define LINEREF_H 0011 0012 #include "TypeUtils.h" 0013 0014 #include <stdlib.h> 0015 #include <type_traits> 0016 0017 #include <QtGlobal> 0018 0019 class LineRef 0020 { 0021 public: 0022 typedef qint32 LineType; 0023 0024 static constexpr LineType invalid = -1; 0025 constexpr inline LineRef() = default; 0026 //cppcheck-suppress noExplicitConstructor 0027 constexpr inline LineRef(const LineType i) { mLineNumber = i; } 0028 //cppcheck-suppress noExplicitConstructor 0029 constexpr inline LineRef(const quint64 i) 0030 { 0031 if(i <= limits<LineType>::max()) 0032 mLineNumber = (LineType)i; 0033 else 0034 mLineNumber = invalid; 0035 } 0036 //cppcheck-suppress noExplicitConstructor 0037 constexpr inline LineRef(const qint64 i) 0038 { 0039 if(i <= limits<LineType>::max() && i >= 0) 0040 mLineNumber = (LineType)i; 0041 else 0042 mLineNumber = invalid; 0043 } 0044 0045 inline operator LineType() const noexcept { return mLineNumber; } 0046 0047 inline operator SafeInt<LineType>() const noexcept { return mLineNumber; } 0048 0049 inline LineRef& operator=(const LineType lineIn) noexcept 0050 { 0051 mLineNumber = lineIn; 0052 return *this; 0053 } 0054 0055 inline LineRef& operator+=(const LineType& inLine) noexcept 0056 { 0057 mLineNumber += inLine; 0058 return *this; 0059 }; 0060 0061 LineRef& operator++() noexcept 0062 { 0063 ++mLineNumber; 0064 return *this; 0065 }; 0066 0067 const LineRef operator++(int) noexcept 0068 { 0069 LineRef line(*this); 0070 ++mLineNumber; 0071 return line; 0072 }; 0073 0074 LineRef& operator--() noexcept 0075 { 0076 --mLineNumber; 0077 return *this; 0078 }; 0079 0080 const LineRef operator--(int) noexcept 0081 { 0082 LineRef line(*this); 0083 --mLineNumber; 0084 return line; 0085 }; 0086 inline void invalidate() noexcept { mLineNumber = invalid; } 0087 [[nodiscard]] inline bool isValid() const noexcept { return mLineNumber != invalid; } 0088 0089 private: 0090 SafeSignedRange<LineType, invalid> mLineNumber = invalid; 0091 }; 0092 0093 /* 0094 This is here because its easy to unknowingly break these conditions. The resulting 0095 compiler errors are numerous and may be a bit cryptic if you aren't familiar with the C++ language. 0096 Also some IDEs with clangd or ccls integration can automatically check static_asserts 0097 without doing a full compile. 0098 */ 0099 static_assert(std::is_copy_constructible<LineRef>::value, "LineRef must be copy constructible."); 0100 static_assert(std::is_copy_assignable<LineRef>::value, "LineRef must copy assignable."); 0101 static_assert(std::is_move_constructible<LineRef>::value, "LineRef must be move constructible."); 0102 static_assert(std::is_move_assignable<LineRef>::value, "LineRef must be move assignable."); 0103 static_assert(std::is_convertible<LineRef, int>::value, "Can not convert LineRef to int."); 0104 static_assert(std::is_convertible<int, LineRef>::value, "Can not convert int to LineRef."); 0105 0106 using LineType = LineRef::LineType; 0107 0108 //Break in an obvious way if way can't get LineCounts from Qt supplied ints without overflow issues. 0109 static_assert(sizeof(LineType) >= sizeof(qint32)); //Generally assumed by KDiff3 0110 #endif