[gparted] Simplified cleanup_cursor() implementation



commit 82fcb1ef0bb9a592a081dad11f8323f39e9bdea0
Author: Seth Heeren <sgheeren hotmail com>
Date:   Fri Dec 17 15:45:47 2010 +0100

    Simplified cleanup_cursor() implementation
    
    I hit this performance bug when I cloneda 40G NTFS partition. The actual
    copy was done in under 11 minutes. After that I was shocked to find that
    gparted would spend over 12 minutes in cleanup_cursor, pegging a CPU
    core. (On a quad core desktop...)
    
    Simply replacing the ustring with std::string would reduce the time to
    about 1.5 minutes. Still bad. Also, I didn't want to lose UTF8
    awareness.
    
    So I rewrote the algorithm in 'streaming mode'. This has the (potential)
    drawback that locale conversions are done, but performs well and
    - IMHO - is a lot more readable.
    
    On a minor note: this implementation correctly handles backspaces at the
    start of a line.

 src/Utils.cc |   45 ++++++++++++++++++++++-----------------------
 1 files changed, 22 insertions(+), 23 deletions(-)
---
diff --git a/src/Utils.cc b/src/Utils.cc
index 7c419d8..153fabb 100644
--- a/src/Utils.cc
+++ b/src/Utils.cc
@@ -422,34 +422,33 @@ Glib::ustring Utils::trim( const Glib::ustring & src, const Glib::ustring & c /*
 
 Glib::ustring Utils::cleanup_cursor( const Glib::ustring & text )
 {
-	//Clean up text for commands that use cursoring to display progress.
-	Glib::ustring str = text;
-	//remove backspace '\b' and delete previous character.  Used in mke2fs output.
-	for ( unsigned int index = str .find( "\b" ) ; index < str .length() ; index = str .find( "\b" ) ) {
-		if ( index > 0 )
-			str .erase( index - 1, 2 ) ;
-		else
-			str .erase( index, 1 ) ;
-	}
+	std::istringstream in(text);
+	std::ostringstream out;
+	char ch;
+	std::streampos startofline = out.tellp();
 
-	//Remove carriage return and line up to previous line feed.  Used in ntfsclone output.
-	//NOTE:  Normal linux line end is line feed.  DOS uses CR + LF.
-	for ( unsigned int index1 = str .find( "\r") ; index1 < str .length() ; index1 = str .find( "\r" ) )
+	while (in.get(ch))
 	{
-		//Only process if next character is not a LF.
-		if ( str .at(index1 + 1) != '\n')
+		switch(ch)
 		{
-			//find point to start erase from.
-			unsigned int index2 = str .rfind( "\n", index1 ) ;
-			//find end point to erase up to.
-			unsigned int index3 = str .find( "\n", index1 ) ;
-			unsigned int index4 = str .rfind( "\r", index3 ) ;
-			//perform erase if indices are valid
-			if ( ( index2 <= index1 ) && ( index4 > index2 ) && ( index4 < str .length() ) )
-				str .erase( index2 + 1, index4 - index2 ) ;
+			case '\r':
+				if ('\n' != in.peek()) // for windows CRLF
+					out.seekp(startofline);
+				else
+					out.put(ch);
+				break;
+			case '\b':
+				if (out.tellp() > startofline)
+					out.seekp(out.tellp()-1ll);
+				break;
+			default:
+				out.put(ch);
 		}
+		if (ch == '\n')
+		 	startofline = out.tellp();
 	}
-	return str;
+
+	return out.str();
 }
 
 Glib::ustring Utils::get_lang()



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]