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

RFC: [Logging] Add escape(), noescape() stream modifiers to QDebug

    XMLWordPrintable

Details

    • Suggestion
    • Resolution: Unresolved
    • P2: Important
    • None
    • 5.4.0
    • Core: I/O

    Description

      Proposal

      This is a follow-up proposal for QTBUG-37146. Add modifiers to the QDebug stream which enables or disables escaping of special characters of QByteArrays (and maybe QStrings). Add functions QDebug::escape and QDebug::noescape for this.

      Rationale

      Debugging binary data is sometimes anoying, when it contains non-printable characters. You had to manually replace them with something printable. When the data contains a null character, it gets truncated due to how the destructor of QDebug will print the buffer. Example:

      QByteArray ba("hello\0world", 11); // Manual size required since C-string literal contains a null char
      qDebug() << ba;
      

      will print

      "hello
      

      A manual solution is to replace the null character before printing. What we actually want to see (as a developer; remember, it's about debugging raw data) is

      "hello\0world"
      

      or something similar.

      The same problem exists for double quote characters (What if the binary data equals "foo\" \"bar"? It gets usually printed as "foo" "bar". But how many values are these? We can't tell from looking at the output.) as well as other non-printable characters.

      It would be ideal if we could specify separately weather the following set of characters is escaped using a backslash:

      • The null character
      • Non-printable characters
      • Double-quotes

      If any of the above is enabled, the backslash itself is escaped. If all of the above are enabled, the output is a valid C string literal.

      Suggested Change

      For the separate encodings above, a set of flags is added:

      Qt::EscapeNothing
      Qt::EscapeNullCharacter            // includes backslash itself
      Qt::EscapeNonPrintableCharacters   // includes backslash itself and null character
      Qt::EscapeDoubleQuote              // includes backslash itself           
      Qt::EscapeStringLiteral = Qt::EscapeNullCharacter | Qt::EscapeNonPrintableCharacters | Qt::EscapeDoubleQuote
      

      The values, names and place for this enum can be discussed.

      A value of this flag is added to the internal state of a QDebug instance.

      The following functions are added to the QDebug class to modify this state:

      QDebug & escape(Qt::EscapeFlags flags = <SOME DEFAULT>) {
          // Set internal state to `flags`.
          return *this;
      }
      
      QDebug & noescape() {
          return escape(Qt::EscapeNothing);
      }
      

      I suggest the default value to be Qt::EscapeStringLiteral, since it's the most informative way to debug raw data.

      I suggest that the state affects how QByteArray is printed, but neither C strings nor QStrings. See below for QStrings.

      Default state of QDebug

      I suggest that qDebug() is initally in the state Qt::EscapeStringLiteral, since this type of logging messages is typically used to report debug information to the developer.

      For the other types of streams (qWarning, qCritical, qFatal, etc.), it should be Qt::EscapeNothing, since they are not used to debug something but rather for reporting messages to the end-user.

      Example

      The example from above

      QByteArray ba("hello\0world", 11);
      qDebug() << ba;
      

      now prints

      "hello\0world"
      

      as a developer expects. Also, the following

      QByteArray ba("hello\nworld, foo\" \"bar!", 11);
      qDebug() << ba;
      

      now prints

      "hello\nworld, foo\" \"bar!"
      

      instead of the very strange output you get without escaping:

      "hello
      world, foo" "bar!"
      

      But if the developer decides to force this format, he writes

      qDebug().noescape() << ba;

      On the other hand, if he wants to print escaped QByteArrays in a warning message, he writes

      qWarning().escape() << ba;

      Compatibility

      This change (in particular the default state) will change the default behavior of qDebug. In my opinion, a developer should not rely on the format of debug messages.

      I'm not sure if and to what degree this change affects source and binary compatibility.

      Beyond this Suggestion

      We should also consider similar changes for the output of QString. For this, we need to discuss how to print non-ASCII unicode characters (which was recently discussed on the development mailing list).

      Attachments

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

        Activity

          People

            kkohne Kai Köhne
            leemes Sebastian Lehmann
            Votes:
            1 Vote for this issue
            Watchers:
            5 Start watching this issue

            Dates

              Created:
              Updated:

              Gerrit Reviews

                There are no open Gerrit changes