[gparted] Simplified cleanup_cursor() implementation
- From: Curtis Gedak <gedakc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gparted] Simplified cleanup_cursor() implementation
- Date: Sun, 27 Mar 2011 16:39:27 +0000 (UTC)
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]