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 /*******************************************************************************
31  * Namespace / Forward Declarations
32  ******************************************************************************/
33 namespace librepcb {
34 
35 class SExpression;
36 
45 template <typename T>
46 SExpression serialize(const T& obj);
47 
56 template <typename T>
57 T deserialize(const SExpression& node);
58 
59 /*******************************************************************************
60  * Class SExpression
61  ******************************************************************************/
62 
66 class SExpression final {
67  Q_DECLARE_TR_FUNCTIONS(SExpression)
68 
69 public:
70  // Types
71  enum class Type {
72  List,
73  Token,
74  String,
75  LineBreak,
76  };
77 
78  // Constructors / Destructor
79  SExpression() noexcept;
80  SExpression(const SExpression& other) noexcept;
81  ~SExpression() noexcept;
82 
83  // Getters
84  const FilePath& getFilePath() const noexcept { return mFilePath; }
85  Type getType() const noexcept { return mType; }
86  bool isList() const noexcept { return mType == Type::List; }
87  bool isToken() const noexcept { return mType == Type::Token; }
88  bool isString() const noexcept { return mType == Type::String; }
89  bool isLineBreak() const noexcept { return mType == Type::LineBreak; }
90  const QString& getName() const;
91  const QString& getValue() const;
99  const QList<SExpression>& getChildren() const noexcept { return mChildren; }
100  QList<SExpression*> getChildren(Type type) noexcept;
101  QList<const SExpression*> getChildren(Type type) const noexcept;
102  QList<SExpression*> getChildren(const QString& name) noexcept;
103  QList<const SExpression*> getChildren(const QString& name) const noexcept;
104 
142  SExpression& getChild(const QString& path);
143  const SExpression& getChild(const QString& path) const;
144 
156  SExpression* tryGetChild(const QString& path) noexcept;
157  const SExpression* tryGetChild(const QString& path) const noexcept;
158 
159  // Setters
160  void setName(const QString& name);
161  void setValue(const QString& value);
162 
163  // General Methods
164  void ensureLineBreak();
165  SExpression& appendList(const QString& name);
166  SExpression& appendChild(const SExpression& child);
167  template <typename T>
168  SExpression& appendChild(const T& obj) {
169  appendChild(serialize(obj));
170  return *this;
171  }
172  template <typename T>
173  SExpression& appendChild(const QString& child, const T& obj) {
174  return appendList(child).appendChild(obj);
175  }
176  void removeChild(const SExpression& child);
177  void removeChildrenWithNodeRecursive(const SExpression& search) noexcept;
178  void replaceRecursive(const SExpression& search,
179  const SExpression& replace) noexcept;
180  QByteArray toByteArray() const;
181 
182  // Operator Overloadings
183  bool operator==(const SExpression& rhs) const noexcept;
184  bool operator!=(const SExpression& rhs) const noexcept {
185  return !(*this == rhs);
186  }
187  bool operator<(const SExpression& rhs) const noexcept;
188  SExpression& operator=(const SExpression& rhs) noexcept;
189 
190  // Static Methods
191  static SExpression createList(const QString& name);
192  static SExpression createToken(const QString& token);
193  static SExpression createString(const QString& string);
194  static SExpression createLineBreak();
195  static SExpression parse(const QByteArray& content, const FilePath& filePath);
196 
197 private: // Methods
198  SExpression(Type type, const QString& value);
199 
200  bool isMultiLine() const noexcept;
201  static bool skipLineBreaks(const QList<SExpression>& children,
202  int& index) noexcept;
203  static SExpression parse(const QString& content, int& index,
204  const FilePath& filePath);
205  static SExpression parseList(const QString& content, int& index,
206  const FilePath& filePath);
207  static QString parseToken(const QString& content, int& index,
208  const FilePath& filePath);
209  static QString parseString(const QString& content, int& index,
210  const FilePath& filePath);
211  static void skipWhitespaceAndComments(const QString& content, int& index,
212  bool skipNewline = false);
213  static QString escapeString(const QString& string) noexcept;
214  static bool isValidToken(const QString& token) noexcept;
215  static bool isValidTokenChar(const QChar& c) noexcept;
216  QString toString(int indent) const;
217 
218 private: // Data
220  QString mValue;
221  QList<SExpression> mChildren;
223 };
224 
225 /*******************************************************************************
226  * Non-Member Functions
227  ******************************************************************************/
228 
229 inline uint qHash(const SExpression& node, uint seed = 0) noexcept {
230  switch (node.getType()) {
232  return ::qHash(static_cast<int>(node.getType()), seed);
236  qMakePair(static_cast<int>(node.getType()), node.getValue()), seed);
238  const QList<SExpression>& children = node.getChildren();
239  return ::qHashRange(children.begin(), children.end(), seed);
240  }
241  default:
242  Q_ASSERT(false);
243  return 0;
244  }
245 }
246 
247 /*******************************************************************************
248  * End of File
249  ******************************************************************************/
250 
251 } // namespace librepcb
252 
253 #endif
const QString & getName() const
Definition: sexpression.cpp:62
void setValue(const QString &value)
Definition: sexpression.cpp:179
bool isString() const noexcept
Definition: sexpression.h:88
const QList< SExpression > & getChildren() const noexcept
Get all children of this node.
Definition: sexpression.h:99
bool operator!=(const SExpression &rhs) const noexcept
Definition: sexpression.h:184
static SExpression createLineBreak()
Definition: sexpression.cpp:384
void ensureLineBreak()
Definition: sexpression.cpp:191
QByteArray toByteArray() const
Definition: sexpression.cpp:242
static bool isValidToken(const QString &token) noexcept
Definition: sexpression.cpp:309
Definition: occmodel.cpp:76
Type
Definition: sexpression.h:71
static QString parseString(const QString &content, int &index, const FilePath &filePath)
Definition: sexpression.cpp:494
SExpression & appendList(const QString &name)
Definition: sexpression.cpp:197
Type getType() const noexcept
Definition: sexpression.h:85
static SExpression createList(const QString &name)
Definition: sexpression.cpp:372
SExpression & getChild(const QString &path)
Get a child by path.
Definition: sexpression.cpp:120
bool isToken() const noexcept
Definition: sexpression.h:87
FilePath mFilePath
Definition: sexpression.h:222
bool isList() const noexcept
Definition: sexpression.h:86
Type mType
Definition: sexpression.h:219
values without quotes (e.g. -12.34)
SExpression & appendChild(const T &obj)
Definition: sexpression.h:168
static SExpression createToken(const QString &token)
Definition: sexpression.cpp:376
QList< SExpression > mChildren
Definition: sexpression.h:221
SExpression & appendChild(const QString &child, const T &obj)
Definition: sexpression.h:173
bool operator==(const SExpression &rhs) const noexcept
Definition: sexpression.cpp:254
static SExpression parseList(const QString &content, int &index, const FilePath &filePath)
Definition: sexpression.cpp:452
QString mValue
either a list name, a token or a string
Definition: sexpression.h:220
static SExpression createString(const QString &string)
Definition: sexpression.cpp:380
SExpression & operator=(const SExpression &rhs) noexcept
Definition: sexpression.cpp:276
has a tag name and an arbitrary number of children
manual line break inside a List
bool isMultiLine() const noexcept
Definition: sexpression.cpp:410
static QString parseToken(const QString &content, int &index, const FilePath &filePath)
Definition: sexpression.cpp:477
bool isLineBreak() const noexcept
Definition: sexpression.h:89
SExpression * tryGetChild(const QString &path) noexcept
Try get a child by path.
Definition: sexpression.cpp:134
This class represents absolute, well-formatted paths to files or directories.
Definition: filepath.h:127
AttributeKey deserialize(const SExpression &node)
Definition: attributekey.h:104
SExpression() noexcept
Definition: sexpression.cpp:41
static void skipWhitespaceAndComments(const QString &content, int &index, bool skipNewline=false)
Definition: sexpression.cpp:548
QString toString(int indent) const
Definition: sexpression.cpp:327
void setName(const QString &name)
Definition: sexpression.cpp:171
values with double quotes (e.g. "Foo!")
void removeChildrenWithNodeRecursive(const SExpression &search) noexcept
Definition: sexpression.cpp:220
SExpression & appendChild(const SExpression &child)
Definition: sexpression.cpp:201
static QString escapeString(const QString &string) noexcept
Definition: sexpression.cpp:288
void replaceRecursive(const SExpression &search, const SExpression &replace) noexcept
Definition: sexpression.cpp:231
static bool skipLineBreaks(const QList< SExpression > &children, int &index) noexcept
Definition: sexpression.cpp:423
static bool isValidTokenChar(const QChar &c) noexcept
Definition: sexpression.cpp:321
~SExpression() noexcept
Definition: sexpression.cpp:55
SExpression serialize(const AttributeKey &obj)
Definition: attributekey.h:99
bool operator<(const SExpression &rhs) const noexcept
Definition: sexpression.cpp:260
const QString & getValue() const
Definition: sexpression.cpp:71
uint qHash(const SExpression &node, uint seed=0) noexcept
Definition: sexpression.h:229
The SExpression class.
Definition: sexpression.h:66
uint qHash(const AttributeKey &key, uint seed=0) noexcept
Definition: attributekey.h:118
void removeChild(const SExpression &child)
Definition: sexpression.cpp:210
static SExpression parse(const QByteArray &content, const FilePath &filePath)
Definition: sexpression.cpp:388
const FilePath & getFilePath() const noexcept
Definition: sexpression.h:84