LibrePCB Developers Documentation
sexpression.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_CORE_SEXPRESSION_H
21#define LIBREPCB_CORE_SEXPRESSION_H
22
23/*******************************************************************************
24 * Includes
25 ******************************************************************************/
26#include "../fileio/filepath.h"
27
28#include <QtCore>
29
30#include <memory>
31#include <vector>
32
33/*******************************************************************************
34 * Namespace / Forward Declarations
35 ******************************************************************************/
36namespace librepcb {
37
38class SExpression;
39
48template <typename T>
49std::unique_ptr<SExpression> serialize(const T& obj);
50
59template <typename T>
60T deserialize(const SExpression& node);
61
62/*******************************************************************************
63 * Class SExpression
64 ******************************************************************************/
65
69class SExpression final {
70 Q_DECLARE_TR_FUNCTIONS(SExpression)
71
72public:
73 // Types
74 enum class Type {
75 List,
76 Token,
77 String,
78 LineBreak,
79 };
80
81 // Constructors / Destructor
82 SExpression() noexcept;
83 SExpression(const SExpression& other) noexcept;
84 ~SExpression() noexcept;
85
86 // Getters
87 const FilePath& getFilePath() const noexcept { return mFilePath; }
88 Type getType() const noexcept { return mType; }
89 bool isList() const noexcept { return mType == Type::List; }
90 bool isToken() const noexcept { return mType == Type::Token; }
91 bool isString() const noexcept { return mType == Type::String; }
92 bool isLineBreak() const noexcept { return mType == Type::LineBreak; }
93 const QString& getName() const;
94 const QString& getValue() const;
95 std::size_t getChildCount() const noexcept { return mChildren.size(); }
96 bool containsChild(const SExpression& child) const noexcept;
97 SExpression& getChild(int index);
98 const SExpression& getChild(int index) const;
99 QList<SExpression*> getChildren(Type type) noexcept;
100 QList<const SExpression*> getChildren(Type type) const noexcept;
101 QList<SExpression*> getChildren(const QString& name) noexcept;
102 QList<const SExpression*> getChildren(const QString& name) const noexcept;
103
141 SExpression& getChild(const QString& path);
142 const SExpression& getChild(const QString& path) const;
143
155 SExpression* tryGetChild(const QString& path) noexcept;
156 const SExpression* tryGetChild(const QString& path) const noexcept;
157
158 // Setters
159 void setName(const QString& name);
160 void setValue(const QString& value);
161
162 // General Methods
163 void ensureLineBreak();
164 SExpression& appendList(const QString& name);
165 void appendChild(std::unique_ptr<SExpression> child);
166 template <typename T>
167 SExpression& appendChild(const T& obj) {
169 return *mChildren.back();
170 }
171 void appendChild(const QString& child, std::unique_ptr<SExpression> obj) {
172 Q_ASSERT(obj);
173 appendList(child).appendChild(std::move(obj));
174 }
175 template <typename T>
176 SExpression& appendChild(const QString& child, const T& obj) {
177 appendChild(child, serialize(obj));
178 return *mChildren.back();
179 }
180 void removeChild(const SExpression& child);
181 void removeChildrenWithNodeRecursive(const SExpression& search) noexcept;
182 void replaceRecursive(const SExpression& search,
183 const SExpression& replace) noexcept;
184 QByteArray toByteArray() const;
185
186 // Operator Overloadings
187 bool operator==(const SExpression& rhs) const noexcept;
188 bool operator!=(const SExpression& rhs) const noexcept {
189 return !(*this == rhs);
190 }
191 bool operator<(const SExpression& rhs) const noexcept;
192 SExpression& operator=(const SExpression& rhs) noexcept;
193
194 // Static Methods
195 static std::unique_ptr<SExpression> createList(const QString& name);
196 static std::unique_ptr<SExpression> createToken(const QString& token);
197 static std::unique_ptr<SExpression> createString(const QString& string);
198 static std::unique_ptr<SExpression> createLineBreak();
199 static std::unique_ptr<SExpression> parse(const QByteArray& content,
200 const FilePath& filePath);
201
202private: // Methods
203 SExpression(Type type, const QString& value);
204
205 bool isMultiLine() const noexcept;
206 static bool skipLineBreaks(
207 const std::vector<std::unique_ptr<SExpression>>& children,
208 int& index) noexcept;
209 static std::unique_ptr<SExpression> parse(const QString& content, int& index,
210 const FilePath& filePath);
211 static std::unique_ptr<SExpression> parseList(const QString& content,
212 int& index,
213 const FilePath& filePath);
214 static QString parseToken(const QString& content, int& index,
215 const FilePath& filePath);
216 static QString parseString(const QString& content, int& index,
217 const FilePath& filePath);
218 static void skipWhitespaceAndComments(const QString& content, int& index,
219 bool skipNewline = false);
220 static QString escapeString(const QString& string) noexcept;
221 static bool isValidToken(const QString& token) noexcept;
222 static bool isValidTokenChar(const QChar& c) noexcept;
223 QString toString(int indent) const;
224
225private: // Data
227 QString mValue;
228 // Note: For memory-safe removal operations we don't use a Qt container class!
229 std::vector<std::unique_ptr<SExpression>> mChildren;
231
232 // qHash() needs access to mChildrenNew.
233 friend uint qHash(const SExpression& node, uint seed) noexcept;
234};
235
236/*******************************************************************************
237 * Non-Member Functions
238 ******************************************************************************/
239
240uint qHash(const SExpression& node, uint seed = 0) noexcept;
241uint qHash(const std::unique_ptr<SExpression>& ptr, uint seed = 0) noexcept;
242
243/*******************************************************************************
244 * End of File
245 ******************************************************************************/
246
247} // namespace librepcb
248
249#endif
This class represents absolute, well-formatted paths to files or directories.
Definition: filepath.h:129
The SExpression class.
Definition: sexpression.h:69
void appendChild(const QString &child, std::unique_ptr< SExpression > obj)
Definition: sexpression.h:171
SExpression * tryGetChild(const QString &path) noexcept
Try get a child by path.
Definition: sexpression.cpp:149
void removeChild(const SExpression &child)
Definition: sexpression.cpp:226
void removeChildrenWithNodeRecursive(const SExpression &search) noexcept
Definition: sexpression.cpp:236
Type
Definition: sexpression.h:74
@ String
values with double quotes (e.g. "Foo!")
@ Token
values without quotes (e.g. -12.34)
@ List
has a tag name and an arbitrary number of children
@ LineBreak
manual line break inside a List
SExpression & appendChild(const QString &child, const T &obj)
Definition: sexpression.h:176
static bool isValidToken(const QString &token) noexcept
Definition: sexpression.cpp:334
static void skipWhitespaceAndComments(const QString &content, int &index, bool skipNewline=false)
Definition: sexpression.cpp:578
static bool skipLineBreaks(const std::vector< std::unique_ptr< SExpression > > &children, int &index) noexcept
Definition: sexpression.cpp:449
SExpression & appendList(const QString &name)
Definition: sexpression.cpp:212
QList< SExpression * > getChildren(Type type) noexcept
Definition: sexpression.cpp:94
const QString & getName() const
Definition: sexpression.cpp:62
bool containsChild(const SExpression &child) const noexcept
Definition: sexpression.cpp:79
static QString escapeString(const QString &string) noexcept
Definition: sexpression.cpp:311
static std::unique_ptr< SExpression > createString(const QString &string)
Definition: sexpression.cpp:405
QByteArray toByteArray() const
Definition: sexpression.cpp:259
bool operator!=(const SExpression &rhs) const noexcept
Definition: sexpression.h:188
FilePath mFilePath
Definition: sexpression.h:230
bool isList() const noexcept
Definition: sexpression.h:89
bool isMultiLine() const noexcept
Definition: sexpression.cpp:436
std::vector< std::unique_ptr< SExpression > > mChildren
Definition: sexpression.h:229
Type getType() const noexcept
Definition: sexpression.h:88
bool isString() const noexcept
Definition: sexpression.h:91
const FilePath & getFilePath() const noexcept
Definition: sexpression.h:87
const QString & getValue() const
Definition: sexpression.cpp:71
SExpression() noexcept
Definition: sexpression.cpp:41
void ensureLineBreak()
Definition: sexpression.cpp:206
QString mValue
either a list name, a token or a string
Definition: sexpression.h:227
static QString parseToken(const QString &content, int &index, const FilePath &filePath)
Definition: sexpression.cpp:507
static std::unique_ptr< SExpression > parse(const QByteArray &content, const FilePath &filePath)
Definition: sexpression.cpp:414
QString toString(int indent) const
Definition: sexpression.cpp:352
static std::unique_ptr< SExpression > createToken(const QString &token)
Definition: sexpression.cpp:401
SExpression & getChild(int index)
Definition: sexpression.cpp:86
static bool isValidTokenChar(const QChar &c) noexcept
Definition: sexpression.cpp:346
static std::unique_ptr< SExpression > parseList(const QString &content, int &index, const FilePath &filePath)
Definition: sexpression.cpp:480
friend uint qHash(const SExpression &node, uint seed) noexcept
Definition: sexpression.cpp:762
void setName(const QString &name)
Definition: sexpression.cpp:186
static std::unique_ptr< SExpression > createList(const QString &name)
Definition: sexpression.cpp:397
SExpression & appendChild(const T &obj)
Definition: sexpression.h:167
bool isLineBreak() const noexcept
Definition: sexpression.h:92
void setValue(const QString &value)
Definition: sexpression.cpp:194
bool operator<(const SExpression &rhs) const noexcept
Definition: sexpression.cpp:282
bool operator==(const SExpression &rhs) const noexcept
Definition: sexpression.cpp:271
SExpression & operator=(const SExpression &rhs) noexcept
Definition: sexpression.cpp:296
std::size_t getChildCount() const noexcept
Definition: sexpression.h:95
static QString parseString(const QString &content, int &index, const FilePath &filePath)
Definition: sexpression.cpp:524
static std::unique_ptr< SExpression > createLineBreak()
Definition: sexpression.cpp:409
bool isToken() const noexcept
Definition: sexpression.h:90
void appendChild(std::unique_ptr< SExpression > child)
Definition: sexpression.cpp:217
Type mType
Definition: sexpression.h:226
void replaceRecursive(const SExpression &search, const SExpression &replace) noexcept
Definition: sexpression.cpp:248
Definition: occmodel.cpp:77
std::unique_ptr< SExpression > serialize(const AttributeKey &obj)
Definition: attributekey.h:100
AttributeKey deserialize(const SExpression &node)
Definition: attributekey.h:105