Qt
Internal/Contributor docs for the Qt SDK. <b>Note:</b> These are NOT official API docs; those are found <a href='https://doc.qt.io/'>here</a>.
Loading...
Searching...
No Matches
qjsonwriter.cpp
Go to the documentation of this file.
1// Copyright (C) 2016 The Qt Company Ltd.
2// Copyright (C) 2016 Intel Corporation.
3// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
4
5#include <cmath>
6#include <qlocale.h>
7#include "qjsonwriter_p.h"
8#include "qjson_p.h"
9#include "private/qstringconverter_p.h"
10#include <private/qnumeric_p.h>
11#include <private/qcborvalue_p.h>
12
14
15using namespace QJsonPrivate;
16
17static void objectContentToJson(const QCborContainerPrivate *o, QByteArray &json, int indent, bool compact);
18static void arrayContentToJson(const QCborContainerPrivate *a, QByteArray &json, int indent, bool compact);
19
20static inline uchar hexdig(uint u)
21{
22 return (u < 0xa ? '0' + u : 'a' + u - 0xa);
23}
24
26{
27 // give it a minimum size to ensure the resize() below always adds enough space
28 QByteArray ba(qMax(s.size(), 16), Qt::Uninitialized);
29
30 auto ba_const_start = [&]() { return reinterpret_cast<const uchar *>(ba.constData()); };
31 uchar *cursor = reinterpret_cast<uchar *>(const_cast<char *>(ba.constData()));
32 const uchar *ba_end = cursor + ba.size();
33 const char16_t *src = s.utf16();
34 const char16_t *const end = s.utf16() + s.size();
35
36 while (src != end) {
37 if (cursor >= ba_end - 6) {
38 // ensure we have enough space
39 qptrdiff pos = cursor - ba_const_start();
40 ba.resize(ba.size()*2);
41 cursor = reinterpret_cast<uchar *>(ba.data()) + pos;
42 ba_end = ba_const_start() + ba.size();
43 }
44
45 char16_t u = *src++;
46 if (u < 0x80) {
47 if (u < 0x20 || u == 0x22 || u == 0x5c) {
48 *cursor++ = '\\';
49 switch (u) {
50 case 0x22:
51 *cursor++ = '"';
52 break;
53 case 0x5c:
54 *cursor++ = '\\';
55 break;
56 case 0x8:
57 *cursor++ = 'b';
58 break;
59 case 0xc:
60 *cursor++ = 'f';
61 break;
62 case 0xa:
63 *cursor++ = 'n';
64 break;
65 case 0xd:
66 *cursor++ = 'r';
67 break;
68 case 0x9:
69 *cursor++ = 't';
70 break;
71 default:
72 *cursor++ = 'u';
73 *cursor++ = '0';
74 *cursor++ = '0';
75 *cursor++ = hexdig(u>>4);
76 *cursor++ = hexdig(u & 0xf);
77 }
78 } else {
79 *cursor++ = (uchar)u;
80 }
81 } else if (QUtf8Functions::toUtf8<QUtf8BaseTraits>(u, cursor, src, end) < 0) {
82 // failed to get valid utf8 use JSON escape sequence
83 *cursor++ = '\\';
84 *cursor++ = 'u';
85 *cursor++ = hexdig(u>>12 & 0x0f);
86 *cursor++ = hexdig(u>>8 & 0x0f);
87 *cursor++ = hexdig(u>>4 & 0x0f);
88 *cursor++ = hexdig(u & 0x0f);
89 }
90 }
91
92 ba.resize(cursor - ba_const_start());
93 return ba;
94}
95
96static void valueToJson(const QCborValue &v, QByteArray &json, int indent, bool compact)
97{
98 QCborValue::Type type = v.type();
99 switch (type) {
100 case QCborValue::True:
101 json += "true";
102 break;
104 json += "false";
105 break;
107 json += QByteArray::number(v.toInteger());
108 break;
109 case QCborValue::Double: {
110 const double d = v.toDouble();
111 if (qt_is_finite(d))
113 else
114 json += "null"; // +INF || -INF || NaN (see RFC4627#section2.4)
115 break;
116 }
118 json += '"';
119 json += escapedString(v.toString());
120 json += '"';
121 break;
123 json += compact ? "[" : "[\n";
125 QJsonPrivate::Value::container(v), json, indent + (compact ? 0 : 1), compact);
126 json += QByteArray(4*indent, ' ');
127 json += ']';
128 break;
129 case QCborValue::Map:
130 json += compact ? "{" : "{\n";
132 QJsonPrivate::Value::container(v), json, indent + (compact ? 0 : 1), compact);
133 json += QByteArray(4*indent, ' ');
134 json += '}';
135 break;
136 case QCborValue::Null:
137 default:
138 json += "null";
139 }
140}
141
142static void arrayContentToJson(const QCborContainerPrivate *a, QByteArray &json, int indent, bool compact)
143{
144 if (!a || a->elements.empty())
145 return;
146
147 QByteArray indentString(4*indent, ' ');
148
149 qsizetype i = 0;
150 while (true) {
151 json += indentString;
152 valueToJson(a->valueAt(i), json, indent, compact);
153
154 if (++i == a->elements.size()) {
155 if (!compact)
156 json += '\n';
157 break;
158 }
159
160 json += compact ? "," : ",\n";
161 }
162}
163
164
165static void objectContentToJson(const QCborContainerPrivate *o, QByteArray &json, int indent, bool compact)
166{
167 if (!o || o->elements.empty())
168 return;
169
170 QByteArray indentString(4*indent, ' ');
171
172 qsizetype i = 0;
173 while (true) {
174 QCborValue e = o->valueAt(i);
175 json += indentString;
176 json += '"';
177 json += escapedString(o->valueAt(i).toString());
178 json += compact ? "\":" : "\": ";
179 valueToJson(o->valueAt(i + 1), json, indent, compact);
180
181 if ((i += 2) == o->elements.size()) {
182 if (!compact)
183 json += '\n';
184 break;
185 }
186
187 json += compact ? "," : ",\n";
188 }
189}
190
191void Writer::objectToJson(const QCborContainerPrivate *o, QByteArray &json, int indent, bool compact)
192{
193 json.reserve(json.size() + (o ? (int)o->elements.size() : 16));
194 json += compact ? "{" : "{\n";
195 objectContentToJson(o, json, indent + (compact ? 0 : 1), compact);
196 json += QByteArray(4*indent, ' ');
197 json += compact ? "}" : "}\n";
198}
199
200void Writer::arrayToJson(const QCborContainerPrivate *a, QByteArray &json, int indent, bool compact)
201{
202 json.reserve(json.size() + (a ? (int)a->elements.size() : 16));
203 json += compact ? "[" : "[\n";
204 arrayContentToJson(a, json, indent + (compact ? 0 : 1), compact);
205 json += QByteArray(4*indent, ' ');
206 json += compact ? "]" : "]\n";
207}
208
\inmodule QtCore
Definition qbytearray.h:57
char * data()
\macro QT_NO_CAST_FROM_BYTEARRAY
Definition qbytearray.h:611
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
Definition qbytearray.h:494
void reserve(qsizetype size)
Attempts to allocate memory for at least size bytes.
Definition qbytearray.h:634
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
Definition qbytearray.h:124
static QByteArray number(int, int base=10)
Returns a byte-array representing the whole number n as text.
void resize(qsizetype size)
Sets the size of the byte array to size bytes.
\inmodule QtCore\reentrant
Definition qcborvalue.h:47
Type
This enum represents the QCborValue type.
Definition qcborvalue.h:70
static QCborContainerPrivate * container(const QCborValue &v)
Definition qjson_p.h:175
static void objectToJson(const QCborContainerPrivate *o, QByteArray &json, int indent, bool compact=false)
static void arrayToJson(const QCborContainerPrivate *a, QByteArray &json, int indent, bool compact=false)
@ FloatingPointShortest
Definition qlocale.h:890
\inmodule QtCore
Definition qstringview.h:78
QCursor cursor
Combined button and popup list for selecting options.
constexpr Initialization Uninitialized
typedef QByteArray(EGLAPIENTRYP PFNQGSGETDISPLAYSPROC)()
static void arrayContentToJson(const QCborContainerPrivate *a, QByteArray &json, int indent, bool compact)
static QByteArray escapedString(QStringView s)
static void objectContentToJson(const QCborContainerPrivate *o, QByteArray &json, int indent, bool compact)
static void valueToJson(const QCborValue &v, QByteArray &json, int indent, bool compact)
static uchar hexdig(uint u)
constexpr const T & qMax(const T &a, const T &b)
Definition qminmax.h:42
static Q_DECL_CONST_FUNCTION bool qt_is_finite(double d)
Definition qnumeric_p.h:117
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLuint GLuint end
GLenum src
GLenum type
GLdouble s
[6]
Definition qopenglext.h:235
unsigned char uchar
Definition qtypes.h:32
ptrdiff_t qptrdiff
Definition qtypes.h:164
ptrdiff_t qsizetype
Definition qtypes.h:165
unsigned int uint
Definition qtypes.h:34
QByteArray ba
[0]