LibrePCB Developers Documentation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
serializablekeyvaluemap.h
Go to the documentation of this file.
1 /*
2  * LibrePCB - Professional EDA for everyone!
3  * Copyright (C) 2013 LibrePCB Developers, see AUTHORS.md for contributors.
4  * https://librepcb.org/
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program. If not, see <http://www.gnu.org/licenses/>.
18  */
19 
20 #ifndef LIBREPCB_SERIALIZABLEKEYVALUEMAP_H
21 #define LIBREPCB_SERIALIZABLEKEYVALUEMAP_H
22 
23 /*******************************************************************************
24  * Includes
25  ******************************************************************************/
26 #include "../elementname.h"
27 #include "serializableobject.h"
28 
29 #include <optional/tl/optional.hpp>
30 
31 #include <QtCore>
32 
33 /*******************************************************************************
34  * Namespace / Forward Declarations
35  ******************************************************************************/
36 namespace librepcb {
37 
38 /*******************************************************************************
39  * Class SerializableKeyValueMap
40  ******************************************************************************/
41 
53 template <typename T>
55  Q_DECLARE_TR_FUNCTIONS(SerializableKeyValueMap)
56 
57 public:
58  // Constructors / Destructor
59  SerializableKeyValueMap() = delete;
61  : mValues(other.mValues) {}
63  const typename T::ValueType& defaultValue) noexcept {
64  mValues.insert("", defaultValue);
65  }
66  explicit SerializableKeyValueMap(const SExpression& node) {
67  foreach (const SExpression& child, node.getChildren(T::tagname)) {
68  QString key;
70  if (child.getChildren().count() > 1) {
71  key = child.getValueByPath<QString>(T::keyname);
72  value = child.getChildByIndex(1);
73  } else {
74  key = QString("");
75  value = child.getChildByIndex(0);
76  }
77  if (mValues.contains(key)) {
78  throw RuntimeError(
79  __FILE__, __LINE__,
80  QString(tr("Key \"%1\" defined multiple times.")).arg(key));
81  }
82  mValues.insert(key, deserializeFromSExpression<typename T::ValueType>(
83  value, false)); // can throw
84  }
85  if (!mValues.contains(QString(""))) {
86  throw RuntimeError(__FILE__, __LINE__,
87  QString(tr("No default %1 defined.")).arg(T::tagname));
88  }
89  }
91 
92  // Getters
93  QStringList keys() const noexcept { return mValues.keys(); }
94  const typename T::ValueType& getDefaultValue() const noexcept {
95  auto i = mValues.find(QString(""));
96  // there must always be a default value!!!
97  Q_ASSERT((i != mValues.end()) && (i.key() == QString("")));
98  return i.value();
99  }
100  bool contains(const QString& key) const noexcept {
101  return mValues.contains(key);
102  }
103  tl::optional<typename T::ValueType> tryGet(const QString& key) const
104  noexcept {
105  auto i = mValues.find(key);
106  if ((i != mValues.end()) && (i.key() == key)) {
107  return i.value();
108  } else {
109  return tl::nullopt;
110  }
111  }
112  const typename T::ValueType& value(const QStringList& keyOrder,
113  QString* usedKey = nullptr) const
114  noexcept {
115  // search in the specified key order
116  foreach (const QString& key, keyOrder) {
117  auto i = mValues.find(key);
118  if ((i != mValues.end()) && (i.key() == key)) {
119  if (usedKey) *usedKey = key;
120  return i.value();
121  }
122  }
123  // use default value (empty key) as fallback
124  if (usedKey) *usedKey = QString("");
125  return getDefaultValue();
126  }
127 
128  // General Methods
129 
130  void setDefaultValue(const typename T::ValueType& value) noexcept {
131  insert(QString(""), value);
132  }
133 
134  void insert(const QString& key, const typename T::ValueType& value) noexcept {
135  mValues.insert(key, value);
136  }
137 
139  void serialize(SExpression& root) const override {
140  for (auto i = mValues.constBegin(); i != mValues.constEnd(); ++i) {
141  SExpression& child = root.appendList(T::tagname, true);
142  if (!i.key().isEmpty()) {
143  child.appendChild(T::keyname, i.key(), false);
144  }
145  child.appendChild(i.value());
146  }
147  }
148 
149  // Operator Overloadings
151  const SerializableKeyValueMap<T>& rhs) noexcept {
152  mValues = rhs.mValues;
153  return *this;
154  }
155  bool operator==(const SerializableKeyValueMap<T>& rhs) const noexcept {
156  return mValues == rhs.mValues;
157  }
158  bool operator!=(const SerializableKeyValueMap<T>& rhs) const noexcept {
159  return mValues != rhs.mValues;
160  }
161 
162 private: // Data
163  QMap<QString, typename T::ValueType> mValues;
164 };
165 
166 /*******************************************************************************
167  * Class LocalizedNameMap
168  ******************************************************************************/
169 
172  static constexpr const char* tagname = "name";
173  static constexpr const char* keyname = "locale";
174 };
176 
177 /*******************************************************************************
178  * Class LocalizedDescriptionMap
179  ******************************************************************************/
180 
182  typedef QString ValueType;
183  static constexpr const char* tagname = "description";
184  static constexpr const char* keyname = "locale";
185 };
188 
189 /*******************************************************************************
190  * Class LocalizedKeywordsMap
191  ******************************************************************************/
192 
194  typedef QString ValueType;
195  static constexpr const char* tagname = "keywords";
196  static constexpr const char* keyname = "locale";
197 };
198 using LocalizedKeywordsMap =
200 
201 /*******************************************************************************
202  * End of File
203  ******************************************************************************/
204 
205 } // namespace librepcb
206 
207 #endif // LIBREPCB_SERIALIZABLEKEYVALUEMAP_H
SerializableKeyValueMap(const SExpression &node)
Definition: serializablekeyvaluemap.h:66
bool contains(const QString &key) const noexcept
Definition: serializablekeyvaluemap.h:100
const QList< SExpression > & getChildren() const
Definition: sexpression.h:87
const SExpression & getChildByIndex(int index) const
Definition: sexpression.cpp:124
SExpression & appendChild(const SExpression &child, bool linebreak)
Definition: sexpression.cpp:173
QString ValueType
Definition: serializablekeyvaluemap.h:194
static constexpr const char * keyname
Definition: serializablekeyvaluemap.h:173
QStringList keys() const noexcept
Definition: serializablekeyvaluemap.h:93
static constexpr const char * tagname
Definition: serializablekeyvaluemap.h:172
void serialize(SExpression &root) const override
Serialize the object into an existing S-Expression node.
Definition: serializablekeyvaluemap.h:139
QMap< QString, typename T::ValueType > mValues
Definition: serializablekeyvaluemap.h:163
QString ValueType
Definition: serializablekeyvaluemap.h:182
SerializableKeyValueMap< T > & operator=(const SerializableKeyValueMap< T > &rhs) noexcept
Definition: serializablekeyvaluemap.h:150
The SerializableObject class is the base class for all classes which need to be serializable/deserial...
Definition: serializableobject.h:46
static constexpr const char * tagname
Definition: serializablekeyvaluemap.h:195
const T::ValueType & getDefaultValue() const noexcept
Definition: serializablekeyvaluemap.h:94
SExpression & appendList(const QString &name, bool linebreak)
Definition: sexpression.cpp:169
Definition: serializablekeyvaluemap.h:193
static constexpr const char * tagname
Definition: serializablekeyvaluemap.h:183
bool operator!=(const SerializableKeyValueMap< T > &rhs) const noexcept
Definition: serializablekeyvaluemap.h:158
~SerializableKeyValueMap() noexcept
Definition: serializablekeyvaluemap.h:90
The RuntimeError class.
Definition: exceptions.h:219
ElementName ValueType
Definition: serializablekeyvaluemap.h:171
void insert(const QString &key, const typename T::ValueType &value) noexcept
Definition: serializablekeyvaluemap.h:134
T getValueByPath(const QString &path, bool throwIfEmpty=false) const
Definition: sexpression.h:104
Definition: serializablekeyvaluemap.h:170
tl::optional< typename T::ValueType > tryGet(const QString &key) const noexcept
Definition: serializablekeyvaluemap.h:103
bool operator==(const SerializableKeyValueMap< T > &rhs) const noexcept
Definition: serializablekeyvaluemap.h:155
const T::ValueType & value(const QStringList &keyOrder, QString *usedKey=nullptr) const noexcept
Definition: serializablekeyvaluemap.h:112
static constexpr const char * keyname
Definition: serializablekeyvaluemap.h:184
Definition: serializablekeyvaluemap.h:181
void setDefaultValue(const typename T::ValueType &value) noexcept
Definition: serializablekeyvaluemap.h:130
static constexpr const char * keyname
Definition: serializablekeyvaluemap.h:196
SerializableKeyValueMap(const SerializableKeyValueMap< T > &other) noexcept
Definition: serializablekeyvaluemap.h:60
The SExpression class.
Definition: sexpression.h:60
SerializableKeyValueMap(const typename T::ValueType &defaultValue) noexcept
Definition: serializablekeyvaluemap.h:62
The SerializableKeyValueMap class provides an easy way to serialize and deserialize ordered key value...
Definition: serializablekeyvaluemap.h:54
type_safe::constrained_type< QString, ElementNameConstraint, ElementNameVerifier > ElementName
Definition: elementname.h:92