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 Mode {
75 LibrePCB,
76 Permissive,
77 };
78 enum class Type {
79 List,
80 Token,
81 String,
82 LineBreak,
83 };
84
85 // Constructors / Destructor
86 SExpression() noexcept;
87 SExpression(const SExpression& other) noexcept;
88 ~SExpression() noexcept;
89
90 // Getters
91 const FilePath& getFilePath() const noexcept { return mFilePath; }
92 Type getType() const noexcept { return mType; }
93 bool isList() const noexcept { return mType == Type::List; }
94 bool isToken() const noexcept { return mType == Type::Token; }
95 bool isString() const noexcept { return mType == Type::String; }
96 bool isLineBreak() const noexcept { return mType == Type::LineBreak; }
97 const QString& getName() const;
98 const QString& getValue() const;
99 std::size_t getChildCount() const noexcept { return mChildren.size(); }
100 bool containsChild(const SExpression& child) const noexcept;
101 SExpression& getChild(int index);
102 const SExpression& getChild(int index) const;
103 QList<SExpression*> getChildren(Type type) noexcept;
104 QList<const SExpression*> getChildren(Type type) const noexcept;
105 QList<SExpression*> getChildren(const QString& name) noexcept;
106 QList<const SExpression*> getChildren(const QString& name) const noexcept;
107
145 SExpression& getChild(const QString& path);
146 const SExpression& getChild(const QString& path) const;
147
159 SExpression* tryGetChild(const QString& path) noexcept;
160 const SExpression* tryGetChild(const QString& path) const noexcept;
161
162 // Setters
163 void setName(const QString& name);
164 void setValue(const QString& value);
165
166 // General Methods
167 void ensureLineBreak();
168 SExpression& appendList(const QString& name);
169 void appendChild(std::unique_ptr<SExpression> child);
170 template <typename T>
171 SExpression& appendChild(const T& obj) {
173 return *mChildren.back();
174 }
175 void appendChild(const QString& child, std::unique_ptr<SExpression> obj) {
176 Q_ASSERT(obj);
177 appendList(child).appendChild(std::move(obj));
178 }
179 template <typename T>
180 SExpression& appendChild(const QString& child, const T& obj) {
181 appendChild(child, serialize(obj));
182 return *mChildren.back();
183 }
184 void removeChild(const SExpression& child);
185 void removeChildrenWithNodeRecursive(const SExpression& search) noexcept;
186 void replaceRecursive(const SExpression& search,
187 const SExpression& replace) noexcept;
188 QByteArray toByteArray(Mode mode = Mode::LibrePCB) const;
189
190 // Operator Overloadings
191 bool operator==(const SExpression& rhs) const noexcept;
192 bool operator!=(const SExpression& rhs) const noexcept {
193 return !(*this == rhs);
194 }
195 bool operator<(const SExpression& rhs) const noexcept;
196 SExpression& operator=(const SExpression& rhs) noexcept;
197
198 // Static Methods
199 static std::unique_ptr<SExpression> createList(const QString& name);
200 static std::unique_ptr<SExpression> createToken(const QString& token);
201 static std::unique_ptr<SExpression> createString(const QString& string);
202 static std::unique_ptr<SExpression> createLineBreak();
203 static std::unique_ptr<SExpression> parse(const QByteArray& content,
204 const FilePath& filePath,
205 Mode mode = Mode::LibrePCB);
206
207private: // Methods
208 SExpression(Type type, const QString& value);
209
210 bool isMultiLine() const noexcept;
211 static bool skipLineBreaks(
212 const std::vector<std::unique_ptr<SExpression>>& children,
213 int& index) noexcept;
214 static std::unique_ptr<SExpression> parse(const QString& content, int& index,
215 const FilePath& filePath,
216 Mode mode);
217 static std::unique_ptr<SExpression> parseList(const QString& content,
218 int& index,
219 const FilePath& filePath,
220 Mode mode);
221 static QString parseToken(const QString& content, int& index,
222 const FilePath& filePath, Mode mode);
223 static QString parseString(const QString& content, int& index,
224 const FilePath& filePath);
225 static void skipWhitespaceAndComments(const QString& content, int& index,
226 bool skipNewline = false);
227 static QString escapeString(const QString& string) noexcept;
228 static bool isValidToken(const QString& token, Mode mode) noexcept;
229 static bool isValidTokenChar(const QChar& c, Mode mode) noexcept;
230 QString toString(int indent, Mode mode) const;
231
232private: // Data
234 QString mValue;
235 // Note: For memory-safe removal operations we don't use a Qt container class!
236 std::vector<std::unique_ptr<SExpression>> mChildren;
238
239 // qHash() needs access to mChildrenNew.
240 friend uint qHash(const SExpression& node, uint seed) noexcept;
241};
242
243/*******************************************************************************
244 * Non-Member Functions
245 ******************************************************************************/
246
247uint qHash(const SExpression& node, uint seed = 0) noexcept;
248uint qHash(const std::unique_ptr<SExpression>& ptr, uint seed = 0) noexcept;
249
250/*******************************************************************************
251 * End of File
252 ******************************************************************************/
253
254} // namespace librepcb
255
256#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:175
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:78
@ 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
QString toString(int indent, Mode mode) const
Definition: sexpression.cpp:354
SExpression & appendChild(const QString &child, const T &obj)
Definition: sexpression.h:180
static void skipWhitespaceAndComments(const QString &content, int &index, bool skipNewline=false)
Definition: sexpression.cpp:584
static bool skipLineBreaks(const std::vector< std::unique_ptr< SExpression > > &children, int &index) noexcept
Definition: sexpression.cpp:452
SExpression & appendList(const QString &name)
Definition: sexpression.cpp:212
static std::unique_ptr< SExpression > parse(const QByteArray &content, const FilePath &filePath, Mode mode=Mode::LibrePCB)
Definition: sexpression.cpp:416
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:407
Mode
Definition: sexpression.h:74
@ LibrePCB
LibrePCB syntax (very strict)
bool operator!=(const SExpression &rhs) const noexcept
Definition: sexpression.h:192
static std::unique_ptr< SExpression > parseList(const QString &content, int &index, const FilePath &filePath, Mode mode)
Definition: sexpression.cpp:484
QByteArray toByteArray(Mode mode=Mode::LibrePCB) const
Definition: sexpression.cpp:259
FilePath mFilePath
Definition: sexpression.h:237
bool isList() const noexcept
Definition: sexpression.h:93
bool isMultiLine() const noexcept
Definition: sexpression.cpp:439
std::vector< std::unique_ptr< SExpression > > mChildren
Definition: sexpression.h:236
Type getType() const noexcept
Definition: sexpression.h:92
bool isString() const noexcept
Definition: sexpression.h:95
const FilePath & getFilePath() const noexcept
Definition: sexpression.h:91
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:234
static std::unique_ptr< SExpression > createToken(const QString &token)
Definition: sexpression.cpp:403
SExpression & getChild(int index)
Definition: sexpression.cpp:86
static QString parseToken(const QString &content, int &index, const FilePath &filePath, Mode mode)
Definition: sexpression.cpp:512
friend uint qHash(const SExpression &node, uint seed) noexcept
Definition: sexpression.cpp:768
void setName(const QString &name)
Definition: sexpression.cpp:186
static std::unique_ptr< SExpression > createList(const QString &name)
Definition: sexpression.cpp:399
SExpression & appendChild(const T &obj)
Definition: sexpression.h:171
bool isLineBreak() const noexcept
Definition: sexpression.h:96
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:99
static QString parseString(const QString &content, int &index, const FilePath &filePath)
Definition: sexpression.cpp:530
static std::unique_ptr< SExpression > createLineBreak()
Definition: sexpression.cpp:411
static bool isValidToken(const QString &token, Mode mode) noexcept
Definition: sexpression.cpp:334
bool isToken() const noexcept
Definition: sexpression.h:94
void appendChild(std::unique_ptr< SExpression > child)
Definition: sexpression.cpp:217
Type mType
Definition: sexpression.h:233
void replaceRecursive(const SExpression &search, const SExpression &replace) noexcept
Definition: sexpression.cpp:248
static bool isValidTokenChar(const QChar &c, Mode mode) noexcept
Definition: sexpression.cpp:346
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