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_MAX, 94 }; 95 96 // Represents a position in a file (line, column) 97 class FilePosition 98 { 99 public: 100 FilePosition() 101 { line_ = -1; column_ = -1; } 102 FilePosition( qint64 line, int column ) 103 { line_ = line; column_ = column; } 104 105 qint64 line() const { return line_; } 106 int column() const { return column_; } 107 108 private: 109 qint64 line_; 110 int column_; 111 }; 112 113 template<typename Iterator> 114 LineNumber lookupLineNumber( Iterator begin, Iterator end, LineNumber lineNum ) 115 { 116 LineNumber lineIndex = 0; 117 Iterator lowerBound = std::lower_bound( begin, end, lineNum ); 118 if ( lowerBound != end ) { 119 lineIndex = std::distance(begin, lowerBound); 120 } 121 else if (begin != end) { 122 lineIndex = begin->lineNumber(); 123 } 124 return lineIndex; 125 } 126 127 #ifndef HAVE_MAKE_UNIQUE 128 #include <memory> 129 130 namespace std { 131 template<typename T, typename... Args> 132 std::unique_ptr<T> make_unique(Args&&... args) { 133 return std::unique_ptr<T>(new T(std::forward<Args>(args)...)); 134 } 135 } 136 #endif 137 138 #ifndef HAVE_OVERRIDE 139 #define override 140 #endif 141 142 #endif 143