File indexing completed on 2024-11-10 11:06:51

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