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. 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: 104 FilePosition() 105 { line_ = -1; column_ = -1; } 106 FilePosition( qint64 line, int column ) 107 { line_ = line; column_ = column; } 108 109 qint64 line() const { return line_; } 110 int column() const { return column_; } 111 112 private: 113 qint64 line_; 114 int column_; 115 }; 116 117 template<typename Iterator> 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> 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