Proposal KLatin1String

Harri Porten porten at kde.org
Fri Mar 26 23:50:12 CET 2004


Hi!

In the "inefficient QString coding practice" thread

  http://lists.kde.org/?t=107918314400001&r=1&w=2

Juergen Pfennig made the point that our cast-safe coding style

  if (extension == QString::fromLatin1(".wav"))

is not very efficient due to the temporary QString creation. Later
discussion evolved around an extra function or class for this purpose.
Find a sample implementation with basic tests attached to this mail.
Cachegrinding my non-representative test program

    int x = 0;
    for (int i = 0; i < 10000; ++i) {
        if (QString("foo") == KLatin1String("foo"))
            ++x;
        if (QString("foo") == KLatin1String("bar"))
            ++x;
        if (QString("foo") == KLatin1String("zilch"))
            ++x;
    }

showed it to be equally fast (actually 1% faster) that the unsafe
operator==(const QString&, const char*). The currently used
QString::fromLatin1() solution is approx. 38% slower (in above case).

I suggest to add a class such as KLatin1String to a kdecore header file.
Simon suggest this naming to be compatible with future Qt versions which
fill feature a similar class. With this solution we will have immediate
benefits and no big porting problems in the future.

The design of the class is open to discussion, of course. Maybe the
pre-calculation of the string length is superfluous. I somewhat counted on
the possibility mentioned by Dirk that a compiler could make the strlen()
call a constant for string literals.

More functions accepting KLatin1String could be added. Like operator+()
and operator+=().

Harri.
-------------- next part --------------
#include <qstring.h>
#include <stdio.h>
#include <assert.h>

class KLatin1String
{
public:
    explicit KLatin1String(const char* s)
        : str(s), len(s ? strlen(s) : (size_t)-1) { }

    const char* data() const { return str; }
    size_t length() const { return len; }

private:
    const char* str;
    size_t len;
};

bool operator==(const QString &s1, const KLatin1String &s2)
{
    if (s1.isNull())
        return s2.data() == 0;
    size_t l = s2.length();
    if (s1.length() != l)
        return false;
    const QChar* uc = s1.unicode();
    const char* c = s2.data();
    for (size_t i = 0; i < l; ++i, ++uc, ++c)
        if (uc->unicode() != (ushort)*c)
            return false;

    return true;
}

bool operator!=(const QString &s1, const KLatin1String &s2)
{
    return !(s1 == s2);
}

bool operator==(const KLatin1String &s1, const QString &s2)
{
    return s2 == s1;
}

bool operator!=(const KLatin1String &s1, const QString &s2)
{
    return !(s2 == s1);
}

int main()
{
    assert(QString::null == KLatin1String(0));
    assert(QString::null != KLatin1String(""));
    assert(QString::fromLatin1("") == KLatin1String(""));
    assert(QString::fromLatin1("x") != KLatin1String(""));
    assert(QString::fromLatin1("a") == KLatin1String("a"));
    assert(QString::fromLatin1("a") != KLatin1String("b"));
    assert(QString::fromUtf8("\xe2\x82\xac") != KLatin1String("?"));
    printf("OK\n");
}


More information about the Kde-optimize mailing list