[geany/geany] 6d0062: Scintilla: speed up converting byte offsets to character offsets

Colomban Wendling git-noreply at xxxxx
Mon Feb 27 13:16:20 UTC 2017


Branch:      refs/heads/master
Author:      Colomban Wendling <ban at herbesfolles.org>
Committer:   Colomban Wendling <ban at herbesfolles.org>
Date:        Mon, 27 Feb 2017 13:16:20 UTC
Commit:      6d0062201ee2701acceed9af0227c61e9777037d
             https://github.com/geany/geany/commit/6d0062201ee2701acceed9af0227c61e9777037d

Log Message:
-----------
Scintilla: speed up converting byte offsets to character offsets

Use a per-line cache to avoid re-computing the offset from the start of
the buffer each time. This dramatically speeds up multiple replacements
on large files.

X-Scintilla-Bug-ID: https://sourceforge.net/p/scintilla/bugs/1910/


Modified Paths:
--------------
    scintilla/gtk/ScintillaGTKAccessible.cxx
    scintilla/gtk/ScintillaGTKAccessible.h

Modified: scintilla/gtk/ScintillaGTKAccessible.cxx
7 lines changed, 7 insertions(+), 0 deletions(-)
===================================================================
@@ -856,6 +856,13 @@ void ScintillaGTKAccessible::NotifyReadOnly() {
 void ScintillaGTKAccessible::Notify(GtkWidget *, gint, SCNotification *nt) {
 	switch (nt->nmhdr.code) {
 		case SCN_MODIFIED: {
+			if (nt->modificationType & (SC_MOD_INSERTTEXT | SC_MOD_DELETETEXT)) {
+				// invalidate character offset cache if applicable
+				const Position line = sci->pdoc->LineFromPosition(nt->position);
+				if (character_offsets.size() > static_cast<size_t>(line + 1)) {
+					character_offsets.resize(line + 1);
+				}
+			}
 			if (nt->modificationType & SC_MOD_INSERTTEXT) {
 				int startChar = CharacterOffsetFromByteOffset(nt->position);
 				int lengthChar = sci->pdoc->CountCharacters(nt->position, nt->position + nt->length);


Modified: scintilla/gtk/ScintillaGTKAccessible.h
16 lines changed, 15 insertions(+), 1 deletions(-)
===================================================================
@@ -20,6 +20,9 @@ class ScintillaGTKAccessible {
 	GtkAccessible *accessible;
 	ScintillaGTK *sci;
 
+	// cache holding character offset for each line start, see CharacterOffsetFromByteOffset()
+	std::vector<Position> character_offsets;
+
 	// cached length of the deletion, in characters (see Notify())
 	int deletionLengthChar;
 	// local state for comparing
@@ -52,7 +55,18 @@ class ScintillaGTKAccessible {
 	}
 
 	int CharacterOffsetFromByteOffset(Position byteOffset) {
-		return sci->pdoc->CountCharacters(0, byteOffset);
+		const Position line = sci->pdoc->LineFromPosition(byteOffset);
+		if (character_offsets.size() <= static_cast<size_t>(line)) {
+			if (character_offsets.empty())
+				character_offsets.push_back(0);
+			for (Position i = character_offsets.size(); i <= line; i++) {
+				const Position start = sci->pdoc->LineStart(i - 1);
+				const Position end = sci->pdoc->LineStart(i);
+				character_offsets.push_back(character_offsets[i - 1] + sci->pdoc->CountCharacters(start, end));
+			}
+		}
+		const Position lineStart = sci->pdoc->LineStart(line);
+		return character_offsets[line] + sci->pdoc->CountCharacters(lineStart, byteOffset);
 	}
 
 	void CharacterRangeFromByteRange(Position startByte, Position endByte, int *startChar, int *endChar) {



--------------
This E-Mail was brought to you by github_commit_mail.py (Source: https://github.com/geany/infrastructure).


More information about the Commits mailing list