1// Copyright (C) 2021 Ford Motor Company
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include <QtCore/qiodevice.h>
5
6#include "qremoteobjectcontainers_p.h"
7#include "qremoteobjectpacket_p.h"
8
9QT_BEGIN_NAMESPACE
10
11QDataStream &operator>>(QDataStream &ds, QtROSequentialContainer &p)
12{
13 QByteArray typeName;
14 quint32 count;
15 ds >> typeName;
16 p.setValueType(typeName);
17 ds >> count;
18 p.reserve(asize: count);
19 QVariant value{p.m_valueType, nullptr};
20 for (quint32 i = 0; i < count; i++) {
21 if (!p.m_valueType.load(stream&: ds, data: value.data())) {
22 qWarning(msg: "QSQ_: unable to load type '%s', returning an empty list.", p.m_valueTypeName.constData());
23 p.clear();
24 break;
25 }
26 p.append(t: value);
27 }
28 return ds;
29}
30
31QDataStream &operator<<(QDataStream &ds, const QtROSequentialContainer &p)
32{
33 ds << p.m_valueTypeName;
34 auto pos = ds.device()->pos();
35 quint32 count = p.size();
36 ds << count;
37 for (quint32 i = 0; i < count; i++) {
38 if (!p.m_valueType.save(stream&: ds, data: p.at(i).data())) {
39 ds.device()->seek(pos);
40 ds.resetStatus();
41 ds << quint32(0);
42 qWarning(msg: "QSQ_: unable to save type '%s'.", p.m_valueTypeName.constData());
43 break;
44 }
45 }
46 return ds;
47}
48
49const char *descopedName(QMetaType type) {
50 auto name = QByteArray::fromRawData(data: type.name(), size: qstrlen(str: type.name()));
51 int index = name.lastIndexOf(c: ':'); // Returns -1 if not found
52 return type.name() + index + 1;
53}
54
55QDataStream &operator>>(QDataStream &ds, QtROAssociativeContainer &p)
56{
57 QByteArray keyTypeName, valueTypeName;
58 quint32 count;
59 ds >> keyTypeName;
60 ds >> valueTypeName;
61 p.setTypes(keyTypeName, valueTypeName);
62 ds >> count;
63 p.m_keys.reserve(asize: count);
64 auto transferType = p.m_keyType;
65 if (p.m_keyType.flags().testFlag(flag: QMetaType::IsEnumeration))
66 transferType = QRemoteObjectPackets::transferTypeForEnum(enumType: p.m_keyType);
67 QVariant key{transferType, nullptr};
68 QVariant value{p.m_valueType, nullptr};
69 for (quint32 i = 0; i < count; i++) {
70 if (!transferType.load(stream&: ds, data: key.data())) {
71 qWarning(msg: "QAS_: unable to load key '%s', returning an empty map.", p.m_keyTypeName.constData());
72 p.clear();
73 break;
74 }
75 if (!p.m_valueType.load(stream&: ds, data: value.data())) {
76 qWarning(msg: "QAS_: unable to load value '%s', returning an empty map.", p.m_valueTypeName.constData());
77 p.clear();
78 break;
79 }
80 if (transferType != p.m_keyType) {
81 bool isFlag = false;
82 QVariant enumKey(key);
83 enumKey.convert(type: p.m_keyType);
84 p.m_keys.append(t: enumKey);
85 if (auto meta = p.m_keyType.metaObject()) {
86 int index = meta->indexOfEnumerator(name: descopedName(type: p.m_keyType));
87 isFlag = meta->enumerator(index).isFlag();
88 }
89 // If multiple flag values are set, toString() returns an empty string
90 // Thus, for flags, we convert the integer value to a string
91 if (isFlag)
92 p.insert(key: key.toString(), value);
93 else
94 p.insert(key: enumKey.toString(), value);
95 } else {
96 p.insert(key: key.toString(), value);
97 p.m_keys.append(t: key);
98 }
99 }
100 return ds;
101}
102
103QDataStream &operator<<(QDataStream &ds, const QtROAssociativeContainer &p)
104{
105 ds << p.m_keyTypeName;
106 ds << p.m_valueTypeName;
107 auto pos = ds.device()->pos();
108 quint32 count = p.size();
109 ds << count;
110 QAssociativeIterable map(&p);
111 QAssociativeIterable::const_iterator iter = map.begin();
112 auto transferType = p.m_keyType;
113 if (p.m_keyType.flags().testFlag(flag: QMetaType::IsEnumeration))
114 transferType = QRemoteObjectPackets::transferTypeForEnum(enumType: p.m_keyType);
115 bool keySaved;
116 for (quint32 i = 0; i < count; i++) {
117 if (transferType != p.m_keyType) {
118 QVariant intKey(iter.key());
119 intKey.convert(type: transferType);
120 keySaved = transferType.save(stream&: ds, data: intKey.data());
121 } else {
122 keySaved = transferType.save(stream&: ds, data: iter.key().data());
123 }
124 if (!keySaved) {
125 ds.device()->seek(pos);
126 ds.resetStatus();
127 ds << quint32(0);
128 qWarning(msg: "QAS_: unable to save type '%s'.", p.m_valueTypeName.constData());
129 break;
130 }
131 if (!p.m_valueType.save(stream&: ds, data: iter.value().data())) {
132 ds.device()->seek(pos);
133 ds.resetStatus();
134 ds << quint32(0);
135 qWarning(msg: "QAS_: unable to save type '%s'.", p.m_valueTypeName.constData());
136 break;
137 }
138 iter++;
139 }
140 return ds;
141}
142
143QT_END_NAMESPACE
144

source code of qtremoteobjects/src/remoteobjects/qremoteobjectcontainers.cpp