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 &parameters)
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 &parameters)
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 &parameters)
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 &parameters)
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