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_LIBRARY_COMPONENTSYMBOLVARIANTITEMSUFFIX_H
21 #define LIBREPCB_LIBRARY_COMPONENTSYMBOLVARIANTITEMSUFFIX_H
22 
23 /*******************************************************************************
24  *  Includes
25  ******************************************************************************/
26 #include <librepcb/common/fileio/sexpression.h>
27 #include <type_safe/constrained_type.hpp>
28 
29 #include <QtCore>
30 
31 /*******************************************************************************
32  *  Namespace / Forward Declarations
33  ******************************************************************************/
34 namespace librepcb {
35 namespace library {
36 
37 /*******************************************************************************
38  *  Class ComponentSymbolVariantItemSuffix
39  ******************************************************************************/
40 
41 struct ComponentSymbolVariantItemSuffixVerifier {
42   template <typename Value, typename Predicate>
43   static constexpr auto verify(Value&& val, const Predicate& p) ->
44       typename std::decay<Value>::type {
45     return p(val) ? std::forward<Value>(val)
46                   : (throw RuntimeError(
47                          __FILE__, __LINE__,
48                          QString(QApplication::translate(
49                                      "ComponentSymbolVariantItemSuffix",
50                                      "Invalid component symbol suffix: '%1'"))
51                              .arg(val)),
52                      std::forward<Value>(val));
53   }
54 };
55 
56 struct ComponentSymbolVariantItemSuffixConstraint {
operatorComponentSymbolVariantItemSuffixConstraint57   bool operator()(const QString& value) const noexcept {
58     return QRegularExpression("\\A[0-9a-zA-Z_]{0,16}\\z")
59         .match(value, 0, QRegularExpression::PartialPreferCompleteMatch)
60         .hasMatch();
61   }
62 };
63 
64 /**
65  * ComponentSymbolVariantItemSuffix is a wrapper around QString which guarantees
66  * to contain a valid suffix used for
67  * librepcb::library::ComponentSymbolVariantItem
68  *
69  * Such a suffix is considered as valid if it:
70  *   - contains only the characters [0-9a-zA-Z_-]
71  *   - is not longer than 16 characters
72  *
73  * The constructor throws an exception if constructed from a QString which is
74  * not a valid suffix according these rules.
75  */
76 using ComponentSymbolVariantItemSuffix =
77     type_safe::constrained_type<QString,
78                                 ComponentSymbolVariantItemSuffixConstraint,
79                                 ComponentSymbolVariantItemSuffixVerifier>;
80 
81 }  // namespace library
82 
83 inline bool operator==(const library::ComponentSymbolVariantItemSuffix& lhs,
84                        const QString& rhs) noexcept {
85   return (*lhs) == rhs;
86 }
87 inline bool operator==(
88     const QString& lhs,
89     const library::ComponentSymbolVariantItemSuffix& rhs) noexcept {
90   return lhs == (*rhs);
91 }
92 inline bool operator!=(const library::ComponentSymbolVariantItemSuffix& lhs,
93                        const QString& rhs) noexcept {
94   return (*lhs) != rhs;
95 }
96 inline bool operator!=(
97     const QString& lhs,
98     const library::ComponentSymbolVariantItemSuffix& rhs) noexcept {
99   return lhs != (*rhs);
100 }
101 inline QString operator%(const library::ComponentSymbolVariantItemSuffix& lhs,
102                          const QString& rhs) noexcept {
103   return (*lhs) % rhs;
104 }
105 inline QString operator%(
106     const QString& lhs,
107     const library::ComponentSymbolVariantItemSuffix& rhs) noexcept {
108   return lhs % (*rhs);
109 }
110 
111 template <>
serialize(const library::ComponentSymbolVariantItemSuffix & obj)112 inline SExpression serialize(
113     const library::ComponentSymbolVariantItemSuffix& obj) {
114   return SExpression::createString(*obj);
115 }
116 
117 template <>
deserialize(const SExpression & sexpr,const Version & fileFormat)118 inline library::ComponentSymbolVariantItemSuffix deserialize(
119     const SExpression& sexpr, const Version& fileFormat) {
120   Q_UNUSED(fileFormat);
121   return library::ComponentSymbolVariantItemSuffix(
122       sexpr.getValue());  // can throw
123 }
124 
125 inline QDataStream& operator<<(
126     QDataStream& stream, const library::ComponentSymbolVariantItemSuffix& obj) {
127   stream << *obj;
128   return stream;
129 }
130 
131 inline QDebug operator<<(QDebug stream,
132                          const library::ComponentSymbolVariantItemSuffix& obj) {
133   stream << QString("ComponentSymbolVariantItemSuffix('%1'')").arg(*obj);
134   return stream;
135 }
136 
137 inline uint qHash(const library::ComponentSymbolVariantItemSuffix& key,
138                   uint seed = 0) noexcept {
139   return ::qHash(*key, seed);
140 }
141 
142 /*******************************************************************************
143  *  End of File
144  ******************************************************************************/
145 
146 }  // namespace librepcb
147 
148 #endif  // LIBREPCB_LIBRARY_COMPONENTSYMBOLVARIANTITEMSUFFIX_H
149