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 | |
9 | QT_BEGIN_NAMESPACE |
10 | |
11 | QDataStream &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 | |
31 | QDataStream &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 | |
49 | const 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 | |
55 | QDataStream &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 | |
103 | QDataStream &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 | |
143 | QT_END_NAMESPACE |
144 | |