File indexing completed on 2024-04-14 04:31:28

0001 /*
0002   This file is part of kdev-pg
0003   Copyright 2002-2006 Roberto Raggi <roberto@kdevelop.org>
0004   Copyright 2009 Milian Wolff <mail@milianw.de>
0005 
0006   Permission to use, copy, modify, distribute, and sell this software and its
0007   documentation for any purpose is hereby granted without fee, provided that
0008   the above copyright notice appear in all copies and that both that
0009   copyright notice and this permission notice appear in supporting
0010   documentation.
0011 
0012   The above copyright notice and this permission notice shall be included in
0013   all copies or substantial portions of the Software.
0014 
0015   THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
0016   IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
0017   FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
0018   KDEVELOP TEAM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
0019   AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
0020   CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
0021 */
0022 
0023 //krazy:excludeall=inline
0024 #ifndef KDEV_PG_LOCATION_TABLE_H
0025 #define KDEV_PG_LOCATION_TABLE_H
0026 
0027 #include <QtGlobal>
0028 #include <QtAlgorithms>
0029 
0030 namespace KDevPG
0031 {
0032 
0033 class LocationTable
0034 {
0035 public:
0036   inline LocationTable(qint64 size = 1024)
0037     : lines(nullptr), lineCount(0), currentLine(0), lastLine(0)
0038   {
0039     resize(size);
0040     lines[currentLine++] = 0;
0041   }
0042 
0043   inline ~LocationTable()
0044   {
0045     free(lines);
0046   }
0047 
0048   inline qint64 size() const
0049   { return lineCount; }
0050 
0051   void resize(qint64 size)
0052   {
0053     Q_ASSERT(size > 0);
0054     lines = (qint64*) ::realloc(lines, sizeof(qint64) * size);
0055     lineCount = size;
0056   }
0057 
0058   /**
0059    * Returns the \a line and \a column of the given \a offset in this table.
0060    */
0061   void positionAt(qint64 offset, qint64 *line, qint64 *column) const
0062   {
0063     if ( offset < 0 ) {
0064       // invalid offset
0065       *line = -1;
0066       *column = -1;
0067       return;
0068     } else if ( offset > lines[currentLine - 1] ) {
0069       // overflow
0070       *line = currentLine - 1;
0071       *column = offset - lines[currentLine - 1];
0072       return;
0073     }
0074 
0075     qint64 i = -1;
0076     // search relative to last line (next line and the one after that)
0077     if ( lastLine + 1 < currentLine && lines[lastLine] <= offset ) {
0078       if ( lines[lastLine + 1] > offset ) {
0079         // last matched line matches again
0080         i = lastLine;
0081       } else if ( lastLine + 2 < currentLine && lines[lastLine + 2] > offset ) {
0082         // next line relative to last matched matches
0083         i = lastLine + 1;
0084       }
0085     }
0086     if ( i == -1 ) {
0087       // fallback to binary search
0088       qint64 *it = std::lower_bound(lines, lines + currentLine, offset);
0089       Q_ASSERT(it != lines + currentLine);
0090 
0091       if (*it != offset) {
0092         --it;
0093       }
0094       *line = it - lines;
0095       *column = offset - *it;
0096     } else {
0097       *line = i;
0098       *column = offset - lines[i];
0099     }
0100 
0101     lastLine = *line;
0102   }
0103 
0104   /**
0105    * Marks an \a offset as the character before the first one in the next line.
0106    * The positionAt() function relies on newline() being called properly.
0107    */
0108   inline void newline(qint64 offset)
0109   {
0110     if (currentLine == lineCount)
0111       resize(currentLine * 2);
0112 
0113     lines[currentLine++] = offset+1;
0114   }
0115 
0116   inline qint64 &operator[](int index)
0117   { return lines[index]; }
0118 
0119 protected:
0120   /// An array of input buffer offsets
0121   qint64 *lines;
0122   /// The size of the allocated array
0123   qint64 lineCount;
0124   /// The index to the next index in the lines array
0125   qint64 currentLine;
0126   /// Last line as found by positionAt
0127   mutable qint64 lastLine;
0128 
0129 private:
0130   LocationTable(LocationTable const &other);
0131   void operator=(LocationTable const &other);
0132 };
0133 
0134 }
0135 
0136 #endif // KDEV_PG_LOCATION_TABLE_H
0137