1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 Jochen Becher
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25
26 #pragma once
27
28 #include "parameters.h"
29
30 #include <QList>
31 #include <QHash>
32
33 namespace qark {
34
35 static Flag ENFORCE_REFERENCED_ITEMS;
36
37 // QList
38
39 template<class Archive, class T>
save(Archive & archive,const QList<T> & list,const Parameters &)40 inline void save(Archive &archive, const QList<T> &list, const Parameters &)
41 {
42 archive << tag("qlist");
43 foreach (const T &t, list)
44 archive << attr("item", t);
45 archive << end;
46 }
47
48 template<class Archive, class T>
save(Archive & archive,const QList<T * > & list,const Parameters & parameters)49 inline void save(Archive &archive, const QList<T *> &list, const Parameters ¶meters)
50 {
51 archive << tag("qlist");
52 if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
53 foreach (const T *t, list)
54 archive << ref("item", t);
55 } else {
56 foreach (const T *t, list)
57 archive << attr("item", t);
58 }
59 archive << end;
60 }
61
62 template<class Archive, class T>
load(Archive & archive,QList<T> & list,const Parameters &)63 inline void load(Archive &archive, QList<T> &list, const Parameters &)
64 {
65 archive >> tag("qlist");
66 void (QList<T>::*appendMethod)(const T &) = &QList<T>::append;
67 archive >> attr("item", list, appendMethod);
68 archive >> end;
69 }
70
71 template<class Archive, class T>
load(Archive & archive,QList<T * > & list,const Parameters & parameters)72 inline void load(Archive &archive, QList<T *> &list, const Parameters ¶meters)
73 {
74 archive >> tag("qlist");
75 if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
76 // why does the following line not compile but the line below selects the correct function?
77 //archive >> ref<QList<T *>, T * const &>("item", list, &QList<T *>::append);
78 archive >> ref("item", list, &QList<T *>::append);
79 } else {
80 #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
81 using ParameterType = typename QList<T *>::parameter_type;
82 #else
83 using ParameterType = T * const &;
84 #endif
85 void (QList<T *>::*appendMethod)(ParameterType) = &QList<T *>::append;
86 archive >> attr("item", list, appendMethod);
87 }
88 archive >> end;
89 }
90
91 // QSet
92
93 template<class Archive, class T>
save(Archive & archive,const QSet<T> & set,const Parameters &)94 inline void save(Archive &archive, const QSet<T> &set, const Parameters &)
95 {
96 archive << tag("qset");
97 foreach (const T &t, set)
98 archive << attr("item", t);
99 archive << end;
100 }
101
102 template<class Archive, class T>
save(Archive & archive,const QSet<T * > & set,const Parameters & parameters)103 inline void save(Archive &archive, const QSet<T *> &set, const Parameters ¶meters)
104 {
105 archive << tag("qset");
106 if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS)) {
107 foreach (const T *t, set)
108 archive << ref("item", t);
109 } else {
110 foreach (const T *t, set)
111 archive << attr("item", t);
112 }
113 archive << end;
114 }
115
116 namespace impl {
117
118 template<typename T>
insertIntoSet(QSet<T> & set,const T & t)119 void insertIntoSet(QSet<T> &set, const T &t) {
120 set.insert(t);
121 }
122
123 } // namespace impl
124
125 template<class Archive, class T>
load(Archive & archive,QSet<T> & set,const Parameters &)126 inline void load(Archive &archive, QSet<T> &set, const Parameters &)
127 {
128 archive >> tag("qset");
129 archive >> attr("item", set, &impl::insertIntoSet<T>);
130 archive >> end;
131 }
132
133 template<class Archive, class T>
load(Archive & archive,QSet<T * > & set,const Parameters & parameters)134 inline void load(Archive &archive, QSet<T *> &set, const Parameters ¶meters)
135 {
136 archive >> tag("qset");
137 if (parameters.hasFlag(ENFORCE_REFERENCED_ITEMS))
138 archive >> ref("item", set, &impl::insertIntoSet<T *>);
139 else
140 archive >> attr("item", set, &impl::insertIntoSet<T *>);
141 archive >> end;
142 }
143
144 // QHash
145
146 namespace impl {
147
148 template<typename KEY, typename VALUE>
149 class KeyValuePair
150 {
151 public:
152 KeyValuePair() = default;
KeyValuePair(const KEY & key,const VALUE & value)153 KeyValuePair(const KEY &key, const VALUE &value) : m_key(key), m_value(value) { }
154
155 KEY m_key;
156 VALUE m_value;
157 };
158
159 } // namespace impl
160
161 template<class Archive, class KEY, class VALUE>
save(Archive & archive,const impl::KeyValuePair<KEY,VALUE> & pair,const Parameters &)162 inline void save(Archive &archive, const impl::KeyValuePair<KEY, VALUE> &pair, const Parameters &)
163 {
164 archive << tag("pair")
165 << attr("key", pair.m_key)
166 << attr("value", pair.m_value)
167 << end;
168 }
169
170 template<class Archive, class KEY, class VALUE>
load(Archive & archive,impl::KeyValuePair<KEY,VALUE> & pair,const Parameters &)171 inline void load(Archive &archive, impl::KeyValuePair<KEY, VALUE> &pair, const Parameters &)
172 {
173 archive >> tag("pair")
174 >> attr("key", pair.m_key)
175 >> attr("value", pair.m_value)
176 >> end;
177 }
178
179 template<class Archive, class KEY, class VALUE>
save(Archive & archive,const QHash<KEY,VALUE> & hash,const Parameters &)180 inline void save(Archive &archive, const QHash<KEY, VALUE> &hash, const Parameters &)
181 {
182 archive << tag("qhash");
183 for (auto it = hash.begin(); it != hash.end(); ++it) {
184 impl::KeyValuePair<KEY, VALUE> pair(it.key(), it.value());
185 archive << attr("item", pair);
186 }
187 archive << end;
188 }
189
190 namespace impl {
191
192 template<class KEY, class VALUE>
keyValuePairInsert(QHash<KEY,VALUE> & hash,const KeyValuePair<KEY,VALUE> & pair)193 inline void keyValuePairInsert(QHash<KEY, VALUE> &hash, const KeyValuePair<KEY, VALUE> &pair)
194 {
195 hash.insert(pair.m_key, pair.m_value);
196 }
197
198 } // namespace impl
199
200 template<class Archive, class KEY, class VALUE>
load(Archive & archive,QHash<KEY,VALUE> & hash,const Parameters &)201 inline void load(Archive &archive, QHash<KEY, VALUE> &hash, const Parameters &)
202 {
203 archive >> tag("qhash");
204 archive >> attr("item", hash, &impl::keyValuePairInsert<KEY, VALUE>);
205 archive >> end;
206 }
207
208 } // namespace qark
209