summaryrefslogtreecommitdiffstats
path: root/examples/corelib/serialization/cbordump
diff options
context:
space:
mode:
Diffstat (limited to 'examples/corelib/serialization/cbordump')
-rw-r--r--examples/corelib/serialization/cbordump/CMakeLists.txt41
-rwxr-xr-xexamples/corelib/serialization/cbordump/cbortag.py188
-rw-r--r--examples/corelib/serialization/cbordump/doc/images/cbordump.pngbin0 -> 9556 bytes
-rw-r--r--examples/corelib/serialization/cbordump/doc/src/cbordump.qdoc55
-rw-r--r--examples/corelib/serialization/cbordump/main.cpp289
-rw-r--r--examples/corelib/serialization/cbordump/tag-transform.xslt25
6 files changed, 411 insertions, 187 deletions
diff --git a/examples/corelib/serialization/cbordump/CMakeLists.txt b/examples/corelib/serialization/cbordump/CMakeLists.txt
index 542c6f5ad0..b2c3a536e3 100644
--- a/examples/corelib/serialization/cbordump/CMakeLists.txt
+++ b/examples/corelib/serialization/cbordump/CMakeLists.txt
@@ -1,35 +1,34 @@
-# Generated from cbordump.pro.
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
-cmake_minimum_required(VERSION 3.14)
+cmake_minimum_required(VERSION 3.16)
project(cbordump LANGUAGES CXX)
-set(CMAKE_INCLUDE_CURRENT_DIR ON)
-
-set(CMAKE_AUTOMOC ON)
-set(CMAKE_AUTORCC ON)
-set(CMAKE_AUTOUIC ON)
-
-if(NOT DEFINED INSTALL_EXAMPLESDIR)
- set(INSTALL_EXAMPLESDIR "examples")
+if (ANDROID)
+ message(FATAL_ERROR "This project cannot be built on Android.")
endif()
-set(INSTALL_EXAMPLEDIR "${INSTALL_EXAMPLESDIR}/corelib/serialization/cbordump")
+find_package(Qt6 REQUIRED COMPONENTS Core)
-find_package(Qt6 COMPONENTS Core)
+qt_standard_project_setup()
qt_add_executable(cbordump
main.cpp
)
-set_target_properties(cbordump PROPERTIES
- WIN32_EXECUTABLE FALSE
- MACOSX_BUNDLE FALSE
-)
-target_link_libraries(cbordump PUBLIC
- Qt::Core
+
+target_link_libraries(cbordump PRIVATE
+ Qt6::Core
)
install(TARGETS cbordump
- RUNTIME DESTINATION "${INSTALL_EXAMPLEDIR}"
- BUNDLE DESTINATION "${INSTALL_EXAMPLEDIR}"
- LIBRARY DESTINATION "${INSTALL_EXAMPLEDIR}"
+ BUNDLE DESTINATION .
+ RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
+ LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+)
+
+qt_generate_deploy_app_script(
+ TARGET cbordump
+ OUTPUT_SCRIPT deploy_script
+ NO_UNSUPPORTED_PLATFORM_ERROR
)
+install(SCRIPT ${deploy_script})
diff --git a/examples/corelib/serialization/cbordump/cbortag.py b/examples/corelib/serialization/cbordump/cbortag.py
new file mode 100755
index 0000000000..26a0f969e4
--- /dev/null
+++ b/examples/corelib/serialization/cbordump/cbortag.py
@@ -0,0 +1,188 @@
+#!/bin/env python3
+# Copyright (C) 2023 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
+"""Digest cbor-tags.xml file into code for insertion into main.cpp
+
+See main.cpp's comment on how to regenerate its GENERATED CODE.
+See ./cbortag.py --help for further details on how to invoke.
+You can import this is a module without invoking the script.
+"""
+
+def firstChild(parent, tag):
+ """Return parent's first child element with the given tag."""
+ return next(node for node in parent.childNodes
+ if node.nodeType == parent.ELEMENT_NODE and node.nodeName == tag)
+
+def nodeAttrIs(node, attr, seek):
+ """Checks whether the node has a given value for an attribute
+
+ Takes the node to check, the name of the attribute and the value
+ to check against. Returns true if the node does have that value
+ for the named attribute."""
+ if node.nodeType != node.ELEMENT_NODE:
+ return False
+ if node.attributes is None or attr not in node.attributes:
+ return False
+ return node.attributes[attr].value == seek
+
+def getRfcValue(node):
+ """Extract RFC reference from an <xref type="rfc" ...> element
+
+ Some of these have a reference including section details as the
+ body of the element, otherwise the data attribute should identify
+ the RFC. If neither is found, an empty string is returned."""
+ if node.childNodes:
+ return node.childNodes[0].nodeValue # Maybe accumulate several children ?
+ if node.attributes is None or 'data' not in node.attributes:
+ return ''
+ return node.attributes['data'].value
+
+def readRegistry(filename):
+ """Handles the XML parsing and returns the relevant parts.
+
+ Single argument is the path to the cbor-tags.xml file; returns a
+ twople of the title element's text and an interator over the
+ record nodes. Checks some things are as expected while doing so."""
+ from xml.dom.minidom import parse
+ doc = parse(filename).documentElement
+ assert nodeAttrIs(doc, 'id', 'cbor-tags')
+ title = firstChild(doc, 'title').childNodes[0].nodeValue
+ registry = firstChild(doc, 'registry')
+ assert nodeAttrIs(registry, 'id', 'tags')
+ records = (node for node in registry.childNodes if node.nodeName == 'record')
+ return title, records
+
+def digest(record):
+ """Digest a single record from cbor-tags.xml
+
+ If the record is not of interest, returns the twople (None, None).
+ For records of interest, returns (n, t) where n is the numeric tag
+ code of the record and t is a text describing it. If the record,
+ or its semantics field, has an xref child with type="rfc", the RFC
+ mentioned there is included with the text of the semantics; such a
+ record is of interest, provided it has a semantics field and no
+ dash in its value. Records with a value field containing a dash
+ (indicating a range) are not of interest. Records with a value of
+ 256 or above are only of interest if they include an RFC."""
+ data = {}
+ for kid in record.childNodes:
+ if kid.nodeName == 'xref':
+ if not nodeAttrIs(kid, 'type', 'rfc'):
+ continue
+ rfc = getRfcValue(kid)
+ if rfc:
+ # Potentially stomping one taken from semantics
+ data['rfc'] = rfc
+ elif kid.nodeName == 'semantics':
+ text = rfc = ''
+ for part in kid.childNodes:
+ if part.nodeType == kid.TEXT_NODE:
+ text += part.nodeValue
+ elif part.nodeType == kid.ELEMENT_NODE:
+ if part.nodeName != 'xref' or not nodeAttrIs(part, 'type', 'rfc'):
+ continue # potentially append content to text
+ assert not rfc, ('Duplicate RFC ?', rfc, part)
+ rfc = getRfcValue(part)
+ if rfc:
+ if text.endswith('()'):
+ text = text[:-2].rstrip()
+ if 'rfc' not in data:
+ data['rfc'] = rfc
+ data['semantics'] = ' '.join(text.split())
+ elif kid.nodeName == 'value':
+ data['value'] = kid.childNodes[0].nodeValue
+ text = data.get('semantics')
+ if not text or 'value' not in data or '-' in data['value']:
+ return None, None
+ value = int(data['value'])
+ if 'rfc' in data:
+ rfc = data["rfc"].replace('rfc', 'RFC')
+ text = f'{text} [{rfc}]'
+ elif value >= 256:
+ return None, None
+ return value, text
+
+def entries(records):
+ """Digest each record of interest into a value and text.
+
+ The value and text form the raw material of the tagDescriptions
+ array in main.cpp; see digest for which records are retained."""
+ for record in records:
+ value, text = digest(record)
+ if value is not None:
+ yield value, text
+
+def marginBound(text, prior, left, right):
+ """Split up a string literal for tidy display.
+
+ The first parameter, text, is the content of the string literal;
+ quotes shall be added. It may be split into several fragments,
+ each quoted, so as to abide by line length constraints.
+
+ The remaining parameters are integers: prior is the text already
+ present on the line before text is to be added; left is the width
+ of the left margin for all subsequent lines; and right is the
+ right margin to stay within, where possible. The returned string
+ is either a space with the whole quoted text following, to fit on
+ the line already started to length prior, or a sequence of quoted
+ strings, each preceded by a newline and indent of width left."""
+ if prior + 3 + len(text) < right: # 1 for space, 2 for quotes
+ return f' "{text}"'
+ width = right - left - 2 # 2 for the quotes
+ words = iter(text.split(' '))
+ lines, current = [''], [next(words)]
+ for word in words:
+ if len(word) + sum(len(w) + 1 for w in current) > width:
+ line = ' '.join(current)
+ lines.append(f'"{line}"')
+ current = ['', word]
+ else:
+ current.append(word)
+ line = ' '.join(current)
+ lines.append(f'"{line}"')
+ return ('\n' + ' ' * left).join(lines)
+
+def main(argv, speak):
+ """Takes care of driving the process.
+
+ Takes the command-line argument list (whose first entry is the
+ name of this script) and standard output (or compatible stream of
+ your choosing) to which to write data. If the --out option is
+ specified in the arguments, the file it names is used in place of
+ this output stream."""
+ from argparse import ArgumentParser, ArgumentDefaultsHelpFormatter
+ parser = ArgumentParser(
+ description='Digest cbor-tags.xml into code to insert in main.cpp',
+ formatter_class=ArgumentDefaultsHelpFormatter)
+ parser.add_argument('path', help='path of the cbor-tags.xml file',
+ default='cbor-tags.xml')
+ parser.add_argument('--out', help='file to write instead of standard output')
+ args = parser.parse_args(argv[1:])
+ emit = (open(args.out) if args.out else speak).write
+
+ title, records = readRegistry(args.path)
+ emit(f"""\
+struct CborTagDescription
+{{
+ QCborTag tag;
+ const char *description; // with space and parentheses
+}};
+
+// {title}
+static const CborTagDescription tagDescriptions[] = {{
+ // from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
+""")
+
+ for value, text in sorted(entries(records)):
+ prior = f' {{ QCborTag({value}),'
+ body = marginBound(f' ({text})', len(prior), 6, 96)
+ emit(f"{prior}{body} }},\n")
+
+ emit("""\
+ { QCborTag(-1), nullptr }
+};
+""")
+
+if __name__ == '__main__':
+ import sys
+ sys.exit(main(sys.argv, sys.stdout))
diff --git a/examples/corelib/serialization/cbordump/doc/images/cbordump.png b/examples/corelib/serialization/cbordump/doc/images/cbordump.png
new file mode 100644
index 0000000000..d5ff1da0bf
--- /dev/null
+++ b/examples/corelib/serialization/cbordump/doc/images/cbordump.png
Binary files differ
diff --git a/examples/corelib/serialization/cbordump/doc/src/cbordump.qdoc b/examples/corelib/serialization/cbordump/doc/src/cbordump.qdoc
new file mode 100644
index 0000000000..a4dc01116f
--- /dev/null
+++ b/examples/corelib/serialization/cbordump/doc/src/cbordump.qdoc
@@ -0,0 +1,55 @@
+// Copyright (C) 2022 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GFDL-1.3-no-invariants-only
+
+/*!
+ \example serialization/cbordump
+ \examplecategory {Data Processing & I/O}
+ \meta tag {network}
+ \title Parsing and displaying CBOR data
+
+ \brief A demonstration of how to parse files in CBOR format.
+
+ This example shows how to use the QCborStreamReader class directly to parse
+ CBOR content. The \c cbordump program reads content in CBOR format from
+ files or standard input and dumps the decoded content to stdout in a
+ human-readable format. It can output in CBOR diagnostic notation (which is
+ similar to JSON), or it can produce a verbose output where each byte input
+ is displayed with its encoding beside it.
+
+ \sa QCborStreamReader
+
+ \image cbordump.png
+
+ \section1 The CborDumper Class
+
+ The CborDumper class contains a QCborStreamReader object that is initialized
+ using the QFile object argument passed to the CborDumper constructor. Based
+ on the arguments the dump function calls either dumpOne() or
+ dumpOneDetailed() to dump the contents to standard output,
+
+ \snippet serialization/cbordump/main.cpp 0
+
+ \section2 The dumpOne() Function
+
+ Switching on QCborStreamReader::type() enables printing appropriate to the
+ type of the current value in the stream. If the type is an array or map, the
+ value's content is iterated over, and for each entry the dumpOne() function
+ is called recursively with a higher indentation argument. If the type is a
+ tag, it is printed out and dumpOne() is called once without increasing the
+ indentation argument.
+
+ \section2 The dumpOneDetailed() Function
+
+ This function dumps out both the incoming bytes and the decoded contents
+ on the same line. It uses lambda functions to print out the bytes and
+ decoded content, but otherwise has a similar structure as dumpOne().
+
+ \section1 CborTagDescription
+
+ The \c tagDescriptions table, describing the CBOR tags available, is
+ automatically generated from an XML file available from the iana.org
+ website. When \c dumpOneDetailed() reports a tag, it uses its description
+ from this table.
+
+ \sa {CBOR Support in Qt}
+*/
diff --git a/examples/corelib/serialization/cbordump/main.cpp b/examples/corelib/serialization/cbordump/main.cpp
index 928bc024c5..03c940452e 100644
--- a/examples/corelib/serialization/cbordump/main.cpp
+++ b/examples/corelib/serialization/cbordump/main.cpp
@@ -1,52 +1,5 @@
-/****************************************************************************
-**
-** Copyright (C) 2018 Intel Corporation.
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the examples of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:BSD$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** BSD License Usage
-** Alternatively, you may use this file under the terms of the BSD license
-** as follows:
-**
-** "Redistribution and use in source and binary forms, with or without
-** modification, are permitted provided that the following conditions are
-** met:
-** * Redistributions of source code must retain the above copyright
-** notice, this list of conditions and the following disclaimer.
-** * Redistributions in binary form must reproduce the above copyright
-** notice, this list of conditions and the following disclaimer in
-** the documentation and/or other materials provided with the
-** distribution.
-** * Neither the name of The Qt Company Ltd nor the names of its
-** contributors may be used to endorse or promote products derived
-** from this software without specific prior written permission.
-**
-**
-** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-** "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-** LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-** A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-** OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-** SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-** LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-** OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE."
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
+// Copyright (C) 2018 Intel Corporation.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR BSD-3-Clause
#include <QCborStreamReader>
#include <QCommandLineParser>
@@ -61,86 +14,137 @@
#include <stdarg.h>
#include <stdio.h>
+using namespace Qt::StringLiterals;
+
/*
* To regenerate:
* curl -O https://www.iana.org/assignments/cbor-tags/cbor-tags.xml
- * xsltproc tag-transform.xslt cbor-tags.xml
+ * ./cbortag.py cbor-tags.xml
+ *
+ * The XHTML URL mentioned in the comment below is a human-readable version of
+ * the same resource.
*/
// GENERATED CODE
struct CborTagDescription
{
QCborTag tag;
- const char *description; // with space and parentheses
+ const char *description; // with space and parentheses
};
-// CBOR Tags
+// Concise Binary Object Representation (CBOR) Tags
static const CborTagDescription tagDescriptions[] = {
// from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
- { QCborTag(0), " (Standard date/time string; see Section 2.4.1 [RFC7049])" },
- { QCborTag(1), " (Epoch-based date/time; see Section 2.4.1 [RFC7049])" },
- { QCborTag(2), " (Positive bignum; see Section 2.4.2 [RFC7049])" },
- { QCborTag(3), " (Negative bignum; see Section 2.4.2 [RFC7049])" },
- { QCborTag(4), " (Decimal fraction; see Section 2.4.3 [RFC7049])" },
- { QCborTag(5), " (Bigfloat; see Section 2.4.3 [RFC7049])" },
- { QCborTag(16), " (COSE Single Recipient Encrypted Data Object [RFC8152])" },
- { QCborTag(17), " (COSE Mac w/o Recipients Object [RFC8152])" },
- { QCborTag(18), " (COSE Single Signer Data Object [RFC8152])" },
- { QCborTag(21), " (Expected conversion to base64url encoding; see Section 2.4.4.2 [RFC7049])" },
- { QCborTag(22), " (Expected conversion to base64 encoding; see Section 2.4.4.2 [RFC7049])" },
- { QCborTag(23), " (Expected conversion to base16 encoding; see Section 2.4.4.2 [RFC7049])" },
- { QCborTag(24), " (Encoded CBOR data item; see Section 2.4.4.1 [RFC7049])" },
+ { QCborTag(0), " (Standard date/time string; see Section 3.4.1 [RFC8949])" },
+ { QCborTag(1), " (Epoch-based date/time; see Section 3.4.2 [RFC8949])" },
+ { QCborTag(2), " (Positive bignum; see Section 3.4.3 [RFC8949])" },
+ { QCborTag(3), " (Negative bignum; see Section 3.4.3 [RFC8949])" },
+ { QCborTag(4), " (Decimal fraction; see Section 3.4.4 [RFC8949])" },
+ { QCborTag(5), " (Bigfloat; see Section 3.4.4 [RFC8949])" },
+ { QCborTag(16), " (COSE Single Recipient Encrypted Data Object [RFC9052])" },
+ { QCborTag(17), " (COSE Mac w/o Recipients Object [RFC9052])" },
+ { QCborTag(18), " (COSE Single Signer Data Object [RFC9052])" },
+ { QCborTag(19), " (COSE standalone V2 countersignature [RFC9338])" },
+ { QCborTag(21),
+ " (Expected conversion to base64url encoding; see Section 3.4.5.2 [RFC8949])" },
+ { QCborTag(22), " (Expected conversion to base64 encoding; see Section 3.4.5.2 [RFC8949])" },
+ { QCborTag(23), " (Expected conversion to base16 encoding; see Section 3.4.5.2 [RFC8949])" },
+ { QCborTag(24), " (Encoded CBOR data item; see Section 3.4.5.1 [RFC8949])" },
{ QCborTag(25), " (reference the nth previously seen string)" },
{ QCborTag(26), " (Serialised Perl object with classname and constructor arguments)" },
- { QCborTag(27), " (Serialised language-independent object with type name and constructor arguments)" },
+ { QCborTag(27),
+ " (Serialised language-independent object with type name and constructor arguments)" },
{ QCborTag(28), " (mark value as (potentially) shared)" },
{ QCborTag(29), " (reference nth marked value)" },
{ QCborTag(30), " (Rational number)" },
- { QCborTag(32), " (URI; see Section 2.4.4.3 [RFC7049])" },
- { QCborTag(33), " (base64url; see Section 2.4.4.3 [RFC7049])" },
- { QCborTag(34), " (base64; see Section 2.4.4.3 [RFC7049])" },
+ { QCborTag(31), " (Absent value in a CBOR Array)" },
+ { QCborTag(32), " (URI; see Section 3.4.5.3 [RFC8949])" },
+ { QCborTag(33), " (base64url; see Section 3.4.5.3 [RFC8949])" },
+ { QCborTag(34), " (base64; see Section 3.4.5.3 [RFC8949])" },
{ QCborTag(35), " (Regular expression; see Section 2.4.4.3 [RFC7049])" },
- { QCborTag(36), " (MIME message; see Section 2.4.4.3 [RFC7049])" },
- { QCborTag(37), " (Binary UUID ( section 4.1.2))" },
- { QCborTag(38), " (Language-tagged string)" },
+ { QCborTag(36), " (MIME message; see Section 3.4.5.3 [RFC8949])" },
+ { QCborTag(37), " (Binary UUID [RFC4122, Section 4.1.2])" },
+ { QCborTag(38), " (Language-tagged string [RFC9290, Appendix A])" },
{ QCborTag(39), " (Identifier)" },
- { QCborTag(61), " (CBOR Web Token (CWT))" },
- { QCborTag(96), " (COSE Encrypted Data Object [RFC8152])" },
- { QCborTag(97), " (COSE MACed Data Object [RFC8152])" },
- { QCborTag(98), " (COSE Signed Data Object [RFC8152])" },
- { QCborTag(256), " (mark value as having string references)" },
- { QCborTag(257), " (Binary MIME message)" },
- { QCborTag(258), " (Mathematical finite set)" },
- { QCborTag(260), " (Network Address (IPv4 or IPv6 or MAC Address))" },
- { QCborTag(264), " (Decimal fraction with arbitrary exponent)" },
- { QCborTag(265), " (Bigfloat with arbitrary exponent)" },
- { QCborTag(1001), " (extended time)" },
- { QCborTag(1002), " (duration)" },
- { QCborTag(1003), " (period)" },
- { QCborTag(22098), " (hint that indicates an additional level of indirection)" },
- { QCborTag(55799), " (Self-describe CBOR; see Section 2.4.5 [RFC7049])" },
- { QCborTag(15309736), " (RAINS Message)" },
+ { QCborTag(40), " (Multi-dimensional Array, row-major order [RFC8746])" },
+ { QCborTag(41), " (Homogeneous Array [RFC8746])" },
+ { QCborTag(42), " (IPLD content identifier)" },
+ { QCborTag(43), " (YANG bits datatype; see Section 6.7. [RFC9254])" },
+ { QCborTag(44), " (YANG enumeration datatype; see Section 6.6. [RFC9254])" },
+ { QCborTag(45), " (YANG identityref datatype; see Section 6.10. [RFC9254])" },
+ { QCborTag(46), " (YANG instance-identifier datatype; see Section 6.13. [RFC9254])" },
+ { QCborTag(47), " (YANG Schema Item iDentifier (sid); see Section 3.2. [RFC9254])" },
+ { QCborTag(52), " (IPv4, [prefixlen,IPv4], [IPv4,prefixpart] [RFC9164])" },
+ { QCborTag(54), " (IPv6, [prefixlen,IPv6], [IPv6,prefixpart] [RFC9164])" },
+ { QCborTag(61), " (CBOR Web Token (CWT) [RFC8392])" },
+ { QCborTag(63), " (Encoded CBOR Sequence [RFC8742])" },
+ { QCborTag(64), " (uint8 Typed Array [RFC8746])" },
+ { QCborTag(65), " (uint16, big endian, Typed Array [RFC8746])" },
+ { QCborTag(66), " (uint32, big endian, Typed Array [RFC8746])" },
+ { QCborTag(67), " (uint64, big endian, Typed Array [RFC8746])" },
+ { QCborTag(68), " (uint8 Typed Array, clamped arithmetic [RFC8746])" },
+ { QCborTag(69), " (uint16, little endian, Typed Array [RFC8746])" },
+ { QCborTag(70), " (uint32, little endian, Typed Array [RFC8746])" },
+ { QCborTag(71), " (uint64, little endian, Typed Array [RFC8746])" },
+ { QCborTag(72), " (sint8 Typed Array [RFC8746])" },
+ { QCborTag(73), " (sint16, big endian, Typed Array [RFC8746])" },
+ { QCborTag(74), " (sint32, big endian, Typed Array [RFC8746])" },
+ { QCborTag(75), " (sint64, big endian, Typed Array [RFC8746])" },
+ { QCborTag(76), " ((reserved) [RFC8746])" },
+ { QCborTag(77), " (sint16, little endian, Typed Array [RFC8746])" },
+ { QCborTag(78), " (sint32, little endian, Typed Array [RFC8746])" },
+ { QCborTag(79), " (sint64, little endian, Typed Array [RFC8746])" },
+ { QCborTag(80), " (IEEE 754 binary16, big endian, Typed Array [RFC8746])" },
+ { QCborTag(81), " (IEEE 754 binary32, big endian, Typed Array [RFC8746])" },
+ { QCborTag(82), " (IEEE 754 binary64, big endian, Typed Array [RFC8746])" },
+ { QCborTag(83), " (IEEE 754 binary128, big endian, Typed Array [RFC8746])" },
+ { QCborTag(84), " (IEEE 754 binary16, little endian, Typed Array [RFC8746])" },
+ { QCborTag(85), " (IEEE 754 binary32, little endian, Typed Array [RFC8746])" },
+ { QCborTag(86), " (IEEE 754 binary64, little endian, Typed Array [RFC8746])" },
+ { QCborTag(87), " (IEEE 754 binary128, little endian, Typed Array [RFC8746])" },
+ { QCborTag(96), " (COSE Encrypted Data Object [RFC9052])" },
+ { QCborTag(97), " (COSE MACed Data Object [RFC9052])" },
+ { QCborTag(98), " (COSE Signed Data Object [RFC9052])" },
+ { QCborTag(100), " (Number of days since the epoch date 1970-01-01 [RFC8943])" },
+ { QCborTag(101), " (alternatives as given by the uint + 128; see Section 9.1)" },
+ { QCborTag(103), " (Geographic Coordinates)" },
+ { QCborTag(104), " (Geographic Coordinate Reference System WKT or EPSG number)" },
+ { QCborTag(110), " (relative object identifier (BER encoding); SDNV sequence [RFC9090])" },
+ { QCborTag(111), " (object identifier (BER encoding) [RFC9090])" },
+ { QCborTag(112), " (object identifier (BER encoding), relative to 1.3.6.1.4.1 [RFC9090])" },
+ { QCborTag(120), " (Internet of Things Data Point)" },
+ { QCborTag(260),
+ " (Network Address (IPv4 or IPv6 or MAC Address) (DEPRECATED in favor of 52 and 54 for IP"
+ " addresses) [RFC9164])" },
+ { QCborTag(261),
+ " (Network Address Prefix (IPv4 or IPv6 Address + Mask Length) (DEPRECATED in favor of 52"
+ " and 54 for IP addresses) [RFC9164])" },
+ { QCborTag(271),
+ " (DDoS Open Threat Signaling (DOTS) signal channel object, as defined in [RFC9132])" },
+ { QCborTag(1004), " (full-date string [RFC8943])" },
+ { QCborTag(1040), " (Multi-dimensional Array, column-major order [RFC8746])" },
+ { QCborTag(55799), " (Self-described CBOR; see Section 3.4.6 [RFC8949])" },
+ { QCborTag(55800), " (indicates that the file contains CBOR Sequences [RFC9277])" },
+ { QCborTag(55801),
+ " (indicates that the file starts with a CBOR-Labeled Non-CBOR Data label. [RFC9277])" },
{ QCborTag(-1), nullptr }
};
// END GENERATED CODE
enum {
// See RFC 7049 section 2.
- SmallValueBitLength = 5,
- SmallValueMask = (1 << SmallValueBitLength) - 1, /* 0x1f */
- Value8Bit = 24,
- Value16Bit = 25,
- Value32Bit = 26,
- Value64Bit = 27
+ SmallValueBitLength = 5,
+ SmallValueMask = (1 << SmallValueBitLength) - 1, /* 0x1f */
+ Value8Bit = 24,
+ Value16Bit = 25,
+ Value32Bit = 26,
+ Value64Bit = 27
};
+//! [0]
struct CborDumper
{
- enum DumpOption {
- ShowCompact = 0x01,
- ShowWidthIndicators = 0x02,
- ShowAnnotated = 0x04
- };
+ enum DumpOption { ShowCompact = 0x01, ShowWidthIndicators = 0x02, ShowAnnotated = 0x04 };
Q_DECLARE_FLAGS(DumpOptions, DumpOption)
CborDumper(QFile *f, DumpOptions opts_);
@@ -160,6 +164,7 @@ private:
qint64 offset = 0;
DumpOptions opts;
};
+//! [0]
Q_DECLARE_OPERATORS_FOR_FLAGS(CborDumper::DumpOptions)
static int cborNumberSize(quint64 value)
@@ -176,8 +181,7 @@ static int cborNumberSize(quint64 value)
return normalSize;
}
-CborDumper::CborDumper(QFile *f, DumpOptions opts_)
- : opts(opts_)
+CborDumper::CborDumper(QFile *f, DumpOptions opts_) : opts(opts_)
{
// try to mmap the file, this is faster
char *ptr = reinterpret_cast<char *>(f->map(0, f->size(), QFile::MapPrivateOption));
@@ -224,51 +228,54 @@ QCborError CborDumper::dump()
return err;
}
-template <typename T> static inline bool canConvertTo(double v)
+template<typename T>
+static inline bool canConvertTo(double v)
{
+ using TypeInfo = std::numeric_limits<T>;
// The [conv.fpint] (7.10 Floating-integral conversions) section of the
// standard says only exact conversions are guaranteed. Converting
// integrals to floating-point with loss of precision has implementation-
// defined behavior whether the next higher or next lower is returned;
// converting FP to integral is UB if it can't be represented.;
- static_assert(std::numeric_limits<T>::is_integer);
+ static_assert(TypeInfo::is_integer);
- double supremum = ldexp(1, std::numeric_limits<T>::digits);
+ double supremum = ldexp(1, TypeInfo::digits);
if (v >= supremum)
return false;
- if (v < std::numeric_limits<T>::min()) // either zero or a power of two, so it's exact
+ if (v < TypeInfo::min()) // either zero or a power of two, so it's exact
return false;
// we're in range
return v == floor(v);
}
-static QString fpToString(double v, const char *suffix)
+static QString fpToString(double v, QLatin1StringView suffix = ""_L1)
{
if (qIsInf(v))
- return v < 0 ? QStringLiteral("-inf") : QStringLiteral("inf");
+ return v < 0 ? "-inf"_L1 : "inf"_L1;
if (qIsNaN(v))
- return QStringLiteral("nan");
+ return "nan"_L1;
if (canConvertTo<qint64>(v))
- return QString::number(qint64(v)) + ".0" + suffix;
+ return QString::number(qint64(v)) + ".0"_L1 + suffix;
if (canConvertTo<quint64>(v))
- return QString::number(quint64(v)) + ".0" + suffix;
+ return QString::number(quint64(v)) + ".0"_L1 + suffix;
QString s = QString::number(v, 'g', QLocale::FloatingPointShortest);
- if (!s.contains('.') && !s.contains('e'))
- s += '.';
- s += suffix;
+ if (!s.contains(u'.') && !s.contains(u'e'))
+ s += u'.';
+ if (suffix.size())
+ s += suffix;
return s;
};
void CborDumper::dumpOne(int nestingLevel)
{
- QString indent(1, QLatin1Char(' '));
+ QString indent(1, u' ');
QString indented = indent;
if (!opts.testFlag(ShowCompact)) {
- indent = QLatin1Char('\n') + QString(4 * nestingLevel, QLatin1Char(' '));
- indented = QLatin1Char('\n') + QString(4 + 4 * nestingLevel, QLatin1Char(' '));
+ indent = u'\n' + QString(4 * nestingLevel, u' ');
+ indented = u'\n' + QString(4 + 4 * nestingLevel, u' ');
}
switch (reader.type()) {
@@ -308,7 +315,7 @@ void CborDumper::dumpOne(int nestingLevel)
printStringWidthIndicator(r.data.size());
r = reader.readByteArray();
- comma = QLatin1Char(',') + indented;
+ comma = u',' + indented;
}
} else {
auto r = reader.readString();
@@ -317,7 +324,7 @@ void CborDumper::dumpOne(int nestingLevel)
printStringWidthIndicator(r.data.toUtf8().size());
r = reader.readString();
- comma = QLatin1Char(',') + indented;
+ comma = u',' + indented;
}
}
@@ -373,7 +380,7 @@ void CborDumper::dumpOne(int nestingLevel)
if (reader.next()) {
printWidthIndicator(quint64(tag));
printf("(");
- dumpOne(nestingLevel); // same level!
+ dumpOne(nestingLevel); // same level!
printf(")");
}
@@ -405,15 +412,15 @@ void CborDumper::dumpOne(int nestingLevel)
break;
case QCborStreamReader::Float16:
- printf("%s", qPrintable(fpToString(reader.toFloat16(), "f16")));
+ printf("%s", qPrintable(fpToString(reader.toFloat16(), "f16"_L1)));
reader.next();
break;
case QCborStreamReader::Float:
- printf("%s", qPrintable(fpToString(reader.toFloat(), "f")));
+ printf("%s", qPrintable(fpToString(reader.toFloat(), "f"_L1)));
reader.next();
break;
case QCborStreamReader::Double:
- printf("%s", qPrintable(fpToString(reader.toDouble(), "")));
+ printf("%s", qPrintable(fpToString(reader.toDouble())));
reader.next();
break;
case QCborStreamReader::Invalid:
@@ -438,7 +445,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel)
if (cborNumberSize(value) != actualSize)
printf(" (overlong)");
};
- auto print = [=](const char *descr, const char *fmt, ...) {
+ auto print = [&](const char *descr, const char *fmt, ...) {
qint64 prevOffset = offset;
offset = reader.currentOffset();
if (prevOffset == offset)
@@ -466,13 +473,14 @@ void CborDumper::dumpOneDetailed(int nestingLevel)
};
auto printFp = [=](const char *descr, double d) {
- QString s = fpToString(d, "");
+ QString s = fpToString(d);
if (s.size() <= 6)
return print(descr, "%s", qPrintable(s));
return print(descr, "%a", d);
};
- auto printString = [=](const char *descr) {
+ auto printString = [&](const char *descr) {
+ constexpr qsizetype ChunkSizeLimit = std::numeric_limits<int>::max();
QByteArray indent(nestingLevel * 2, ' ');
const char *chunkStr = (reader.isLengthKnown() ? "" : "chunk ");
int width = 48 - indent.size();
@@ -480,8 +488,8 @@ void CborDumper::dumpOneDetailed(int nestingLevel)
qsizetype size = reader.currentStringChunkSize();
if (size < 0)
- return; // error
- if (size >= std::numeric_limits<int>::max()) {
+ return; // error
+ if (size >= ChunkSizeLimit) {
fprintf(stderr, "String length too big, %lli\n", qint64(size));
exit(EXIT_FAILURE);
}
@@ -525,7 +533,7 @@ void CborDumper::dumpOneDetailed(int nestingLevel)
printf(" %s%s", indent.constData(), section.toHex(' ').constData());
// print the decode
- QByteArray spaces(width > 0 ? width - section.size() * 3 + 1: 0, ' ');
+ QByteArray spaces(width > 0 ? width - section.size() * 3 + 1 : 0, ' ');
printf("%s # \"", spaces.constData());
auto ptr = reinterpret_cast<const uchar *>(section.constData());
for (int j = 0; j < section.size(); ++j)
@@ -537,8 +545,8 @@ void CborDumper::dumpOneDetailed(int nestingLevel)
// get the next chunk
size = reader.currentStringChunkSize();
if (size < 0)
- return; // error
- if (size >= std::numeric_limits<int>::max()) {
+ return; // error
+ if (size >= ChunkSizeLimit) {
fprintf(stderr, "String length too big, %lli\n", qint64(size));
exit(EXIT_FAILURE);
}
@@ -676,7 +684,9 @@ void CborDumper::printByteArray(const QByteArray &ba)
break;
case quint8(QCborKnownTags::ExpectedBase64url):
- printf("b64'%s'", ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals).constData());
+ printf("b64'%s'",
+ ba.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals)
+ .constData());
break;
}
}
@@ -717,23 +727,20 @@ int main(int argc, char *argv[])
setlocale(LC_ALL, "C");
QCommandLineParser parser;
- parser.setApplicationDescription(QStringLiteral("CBOR Dumper tool"));
+ parser.setApplicationDescription("CBOR Dumper tool"_L1);
parser.addHelpOption();
- QCommandLineOption compact({QStringLiteral("c"), QStringLiteral("compact")},
- QStringLiteral("Use compact form (no line breaks)"));
+ QCommandLineOption compact({"c"_L1, "compact"_L1}, "Use compact form (no line breaks)"_L1);
parser.addOption(compact);
- QCommandLineOption showIndicators({QStringLiteral("i"), QStringLiteral("indicators")},
- QStringLiteral("Show indicators for width of lengths and integrals"));
+ QCommandLineOption showIndicators({ "i"_L1, "indicators"_L1 },
+ "Show indicators for width of lengths and integrals"_L1);
parser.addOption(showIndicators);
- QCommandLineOption verbose({QStringLiteral("a"), QStringLiteral("annotated")},
- QStringLiteral("Show bytes and annotated decoding"));
+ QCommandLineOption verbose({"a"_L1, "annotated"_L1}, "Show bytes and annotated decoding"_L1);
parser.addOption(verbose);
- parser.addPositionalArgument(QStringLiteral("[source]"),
- QStringLiteral("CBOR file to read from"));
+ parser.addPositionalArgument("[source]"_L1, "CBOR file to read from"_L1);
parser.process(app);
@@ -748,7 +755,7 @@ int main(int argc, char *argv[])
QStringList files = parser.positionalArguments();
if (files.isEmpty())
files << "-";
- for (const QString &file : qAsConst(files)) {
+ for (const QString &file : std::as_const(files)) {
QFile f(file);
if (file == "-" ? f.open(stdin, QIODevice::ReadOnly) : f.open(QIODevice::ReadOnly)) {
if (files.size() > 1)
diff --git a/examples/corelib/serialization/cbordump/tag-transform.xslt b/examples/corelib/serialization/cbordump/tag-transform.xslt
deleted file mode 100644
index 3cc1b9b293..0000000000
--- a/examples/corelib/serialization/cbordump/tag-transform.xslt
+++ /dev/null
@@ -1,25 +0,0 @@
-<?xml version="1.0"?>
-<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:a="http://www.iana.org/assignments" xmlns="http://www.iana.org/assignments" xmlns:_="http://www.iana.org/assignments" xmlns:DEFAULT="http://www.iana.org/assignments" version="1.0">
-<xsl:output omit-xml-declaration="yes" indent="no" method="text"/>
-<xsl:template match="/a:registry[@id='cbor-tags']">struct CborTagDescription
-{
- QCborTag tag;
- const char *description; // with space and parentheses
-};
-
-// <xsl:value-of select="a:registry/a:title"/>
-static const CborTagDescription tagDescriptions[] = {
- // from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
-<xsl:for-each select="a:registry/a:record">
- <xsl:sort select="a:value" data-type="number"/>
- <xsl:if test="a:semantics != ''">
- <xsl:call-template name="row"/>
- </xsl:if>
- </xsl:for-each> { QCborTag(-1), nullptr }
-};
-</xsl:template>
-<xsl:template name="row"> { QCborTag(<xsl:value-of select="a:value"/>), " (<xsl:value-of select="a:semantics"/> <xsl:call-template name="xref"/>)" },
-</xsl:template>
-<xsl:template name="xref"><xsl:if test="a:xref/@type = 'rfc'"> [<xsl:value-of select="translate(a:xref/@data,'rfc','RFC')"/>]</xsl:if>
-</xsl:template>
-</xsl:stylesheet>