Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-37146

RFC: [Logging] Add quote(), noquote() stream modifiers to QDebug

    XMLWordPrintable

Details

    • Suggestion
    • Resolution: Done
    • P2: Important
    • 5.4.0
    • 5.4.0
    • Core: I/O

    Description

      Proposal

      Add quote()/noquote() stream modifiers, and an autoQuote() accessor to QDebug class.

      Rationale

      Piping a QString, QLatin1String, QStringRef, QByteArray object into a QDebug stream automatically quotes the string:

      QString s = "Hello World";
      qDebug() << s;
      

      leads to

      "Hello World"

      which is often undesired.

      qDebug().noquote() << s;
      

      would print

      Hello World

      instead.

      Existing alternatives

      Current alternatives are to either use qDebug in a printf-style way, use qPrintable(), or use toUtf8().constData();

      qDebug("%ls", s.utf16());
      qDebug() << qPrintable(s);
      qDebug() << s.toUtf8().constData();
      

      All of these have draw backs: The printf-style qDebug is more error prone to runtime issues, and does support only printing of POD types. Using qPrintable() is inefficient , and actually does the encoding wrong: it converts toLocal8Bit(), while QDebug expects const char*'s to be UTF-8 encoded. toUtf8().constData() does the encoding right, but is still inefficient, and very verbose.

      Precedence

      QDebug already features the space(), nospace() modifiers, and an autoInsertSpaces() accessor. "nospace()" is a precedence for not using camel case for the modifier.

      Alternative proposals

      Generic QDebug::plain(), QDebug::noplain() modifiers

      A more general modifier could be e.g. called 'bare()', or 'plain()', and would in general reduce the decorations that QDebug::operator<<s() add:

          QStringList strlist;
          strlist << "Hello" << "World";
          qDebug() << strlist;
          qDebug().plain() << strlist;
      

      could print

      ("Hello", "World")
      Hello, World
      

      However, the exact semantics of bare() are then subject to interpretation: Should e.g. the comma separator for lists be removed in this case, too?

      Also, such structures can be easily formatted in user code:

          QStringList strlist;
          qDebug().noquote() << strlist.join("|");
      

      PlainString() class

      We could introduce a PlainString container class that gets an extra QDebug::operator<<(const PlainString &str):

      qDebug() << PlainString(string);
      

      The structure would need explicit constructors for QString, QLatin1String, QStringRef, QByteArray.

      The disadvantage is that it would be yet another 'string related' class in the global namespace. This might be acceptible though if we find a short, but descriptive name...

      Impact

      Binary Size / Performance

      3 exported symbols are added to QDebug, and the size of the private QDebug::Stream structure is increased by a boolean. Furthermore the relevant (inlined) operator<<() methods do need to check for the flag. This means a (slight) code size/runtime penalty for code that does not use the feature. However, performance for existing code that e.g. uses qPrintable(), and is changed to the new API, would benefit.

      (Related to that, it should be evaluated whether selected parts of the QDebug class should be made non-inline.).

      qPrintable

      Since this kills another major use of qPrintable, we might consider deprecating the macro then.

      Binary Compatibilty

      Since all of QDebug is inlined, there is a risk of BC issues in the following scenarios:

      • A QDebug::Stream structure of the old size is created, and passed to code that is compiled with the new version of e.g. operator<<(const QString &).
      • A QDebug::Stream structure of the new size is created, and passed to code that is compiled with the new version of e.g. operator<<(const QString &).

      Unfortunately the QDebug::Stream structure does not feature a version member. One could 'misuse' the version field in QMessageLogContext though, which is a member of QDebug::Stream.

      Source Compatibility

      No SC issues are to be expected.

      Attachments

        For Gerrit Dashboard: QTBUG-37146
        # Subject Branch Project Status CR V

        Activity

          People

            kkohne Kai Köhne
            kkohne Kai Köhne
            Votes:
            3 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes