xref: /glogg/src/utils.h (revision e191a6372ce0efc66787e543b1949479c1e79a59)
1 /*
2  * Copyright (C) 2011, 2013 Nicolas Bonnefon and other contributors
3  *
4  * This file is part of glogg.
5  *
6  * glogg is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * glogg is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with glogg.  If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef UTILS_H
21 #define UTILS_H
22 
23 #include <QtGlobal>
24 
25 #include "config.h"
26 
27 // Line number are unsigned 32 bits for now.
28 typedef uint32_t LineNumber;
29 
30 // Use a bisection method to find the given line number
31 // in a sorted list.
32 // The T type must be a container containing elements that
33 // implement the lineNumber() member.
34 // Returns true if the lineNumber is found, false if not
35 // foundIndex is the index of the found number or the index
36 // of the closest greater element.
lookupLineNumber(const T & list,qint64 lineNumber,int * foundIndex)37 template <typename T> bool lookupLineNumber(
38         const T& list, qint64 lineNumber, int* foundIndex )
39 {
40     int minIndex = 0;
41     int maxIndex = list.size() - 1;
42     // If the list is not empty
43     if ( maxIndex - minIndex >= 0 ) {
44         // First we test the ends
45         if ( list[minIndex].lineNumber() == lineNumber ) {
46             *foundIndex = minIndex;
47             return true;
48         }
49         else if ( list[maxIndex].lineNumber() == lineNumber ) {
50             *foundIndex = maxIndex;
51             return true;
52         }
53 
54         // Then we test the rest
55         while ( (maxIndex - minIndex) > 1 ) {
56             const int tryIndex = (minIndex + maxIndex) / 2;
57             const qint64 currentMatchingNumber =
58                 list[tryIndex].lineNumber();
59             if ( currentMatchingNumber > lineNumber )
60                 maxIndex = tryIndex;
61             else if ( currentMatchingNumber < lineNumber )
62                 minIndex = tryIndex;
63             else if ( currentMatchingNumber == lineNumber ) {
64                 *foundIndex = tryIndex;
65                 return true;
66             }
67         }
68 
69         // If we haven't found anything...
70         // ... end of the list or before the next
71         if ( lineNumber > list[maxIndex].lineNumber() )
72             *foundIndex = maxIndex + 1;
73         else if ( lineNumber > list[minIndex].lineNumber() )
74             *foundIndex = minIndex + 1;
75         else
76             *foundIndex = minIndex;
77     }
78     else {
79         *foundIndex = 0;
80     }
81 
82     return false;
83 }
84 
85 enum class Encoding {
86     ENCODING_AUTO = 0,
87     ENCODING_ISO_8859_1,
88     ENCODING_UTF8,
89     ENCODING_UTF16LE,
90     ENCODING_UTF16BE,
91     ENCODING_CP1251,
92     ENCODING_CP1252,
93     ENCODING_BIG5,
94     ENCODING_GB18030,
95     ENCODING_SHIFT_JIS,
96     ENCODING_KOI8R,
97     ENCODING_MAX,
98 };
99 
100 // Represents a position in a file (line, column)
101 class FilePosition
102 {
103   public:
FilePosition()104     FilePosition()
105     { line_ = -1; column_ = -1; }
FilePosition(qint64 line,int column)106     FilePosition( qint64 line, int column )
107     { line_ = line; column_ = column; }
108 
line()109     qint64 line() const { return line_; }
column()110     int column() const { return column_; }
111 
112   private:
113     qint64 line_;
114     int column_;
115 };
116 
117 template<typename Iterator>
lookupLineNumber(Iterator begin,Iterator end,LineNumber lineNum)118 LineNumber lookupLineNumber( Iterator begin, Iterator end, LineNumber lineNum )
119 {
120     LineNumber lineIndex = 0;
121     Iterator lowerBound = std::lower_bound( begin, end, lineNum );
122     if ( lowerBound != end ) {
123         lineIndex = std::distance(begin, lowerBound);
124     }
125     else if (begin != end) {
126         lineIndex = begin->lineNumber();
127     }
128     return lineIndex;
129 }
130 
131 #ifndef HAVE_MAKE_UNIQUE
132 #include <memory>
133 
134 namespace std {
135 template<typename T, typename... Args>
make_unique(Args &&...args)136 std::unique_ptr<T> make_unique(Args&&... args) {
137         return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
138 }
139 }
140 #endif
141 
142 #ifndef HAVE_OVERRIDE
143 #define override
144 #endif
145 
146 #endif
147