[tested PATCH] let QString::lower() assume lower case input to avoid real_detach()

Roger Larsson kde-optimize@mail.kde.org
Fri, 24 Jan 2003 02:05:03 +0100


--Boundary-00=_/EJM+rGiL4jICAU
Content-Type: text/plain;
  charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: inline

As QString said in the earlier comments "could do this only when we find a=
=20
change". This version does it like that. And works.

This patch optimizes upper too but it is not a common case. At least not
for konqueror. But I have written the code in a similar way to make it
possible to change in a generic template for QString translation functions.

Test results, after running konqueror for a while

		calls done (non empty)	strings that needed change
upper()		  141			  140
lower()		29990			 3624	almost 90% saved!

Summary: Not worth it for upper, definitely worth it for lower.
(You have to create that a temporary QString object anyway since
 lower() is const, but this avoids creating a new QStringData,
 and copying the strings themselves...)

/RogerL

=2D-=20
Roger Larsson
Skellefte=E5
Sweden

--Boundary-00=_/EJM+rGiL4jICAU
Content-Type: text/x-diff;
  charset="iso-8859-1";
  name="qstring-B1.patch"
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename="qstring-B1.patch"

Index: qstring.cpp
===================================================================
RCS file: /home/kde/qt-copy/src/tools/qstring.cpp,v
retrieving revision 1.51
diff -u -3 -p -r1.51 qstring.cpp
--- qstring.cpp	17 Dec 2002 15:04:18 -0000	1.51
+++ qstring.cpp	24 Jan 2003 00:47:09 -0000
@@ -14999,17 +14999,46 @@ QString QString::rightJustify( uint widt
     \sa upper()
 */
 
+int count_lower_strings;
+int count_lower_had_higher;
+
 QString QString::lower() const
 {
     QString s(*this);
     int l=length();
     if ( l ) {
-	s.real_detach(); // could do this only when we find a change
-	register QChar *p=s.d->unicode;
+	QChar *p=s.d->unicode;
 	if ( p ) {
-	    while ( l-- ) {
-		*p = ::lower( *p );
+	    // check if all are lower already
+	    count_lower_strings++; // statistics, remove...
+
+	    QChar c_any, c_wanted;
+
+	    do {
+	      c_any = *p;
+	      c_wanted = ::lower( c_any );
+	    }
+	    while (c_any == c_wanted && --l);
+
+	    if (l) { 
+	      // The last check was different! Since 'l' is not zero
+
+	      count_lower_had_higher++; // statistics, remove...
+
+	      s.real_detach();
+	      s.d->setDirty();
+
+	      // 'p' might have moved due to the detach, recalculate it
+	      // this undoes the earlier post increment
+	      // then update the mismatching char
+	      // Remember: the remaining 'l' was not decremented
+	      p=s.d->unicode + length() - l;  
+	      *p = c_wanted;
+
+	      while (--l) {
 		p++;
+		*p = ::lower( *p ); 
+	      }
 	    }
 	}
     }
@@ -15027,17 +15056,45 @@ QString QString::lower() const
     \sa lower()
 */
 
+int count_upper_strings;
+int count_upper_had_lower;
+
 QString QString::upper() const
 {
     QString s(*this);
     int l=length();
     if ( l ) {
-	s.real_detach(); // could do this only when we find a change
-	register QChar *p=s.d->unicode;
+	QChar *p=s.d->unicode;
 	if ( p ) {
-	    while ( l-- ) {
-		*p = ::upper( *p );
+	    // check if all are upper already
+	    count_upper_strings++; // statistics, remove...
+
+	    QChar c_any, c_wanted;
+
+	    do { 
+	      c_any = *p++;
+	      c_wanted = ::upper( c_any );
+	    }
+	    while (c_any == c_wanted && --l);
+
+	    if ( l ) {  // The last check was different! Since 'l' is not zero
+
+	      count_upper_had_lower++; // statistics, remove...
+
+	      s.real_detach();
+	      s.d->setDirty();
+
+	      // 'p' might have moved due to the detach, recalculate it
+	      // this undoes the earlier post increment
+	      // then update the mismatching char
+	      // Remember: the remaining 'l' was not decremented
+	      p=s.d->unicode + length() - l;
+	      *p = c_wanted;
+
+	      while ( --l ) {
 		p++;
+		*p = ::upper( *p );
+	      }
 	    }
 	}
     }

--Boundary-00=_/EJM+rGiL4jICAU--