1 /*
2  * SPDX-FileCopyrightText: 2021~2021 CSSlayer <wengxt@gmail.com>
3  *
4  * SPDX-License-Identifier: LGPL-2.1-or-later
5  *
6  */
7 #ifndef _FCITX_UTILS_SEMVER_H_
8 #define _FCITX_UTILS_SEMVER_H_
9 
10 #include <cstdint>
11 #include <optional>
12 #include <string>
13 #include <variant>
14 #include <vector>
15 #include "fcitxutils_export.h"
16 #include "log.h"
17 #include "macros.h"
18 
19 #ifdef __DragonFly__
20 #undef major
21 #undef minor
22 #endif
23 
24 namespace fcitx {
25 
26 class FCITXUTILS_EXPORT PreReleaseId {
27 public:
28     explicit PreReleaseId(uint32_t id);
29     explicit PreReleaseId(std::string id);
30 
31     FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE(PreReleaseId);
32 
33     std::string toString() const;
34 
35     bool isNumeric() const;
36     uint32_t numericId() const;
37     const std::string &id() const;
38 
39     int compare(const PreReleaseId &other) const;
40 
41 private:
42     std::variant<std::string, uint32_t> value_;
43 };
44 
45 /**
46  * @brief Provide a Semantic version 2.0 implementation
47  *
48  * @since 5.0.6
49  */
50 class FCITXUTILS_EXPORT SemanticVersion {
51 public:
52     SemanticVersion() = default;
53     FCITX_INLINE_DEFINE_DEFAULT_DTOR_COPY_AND_MOVE(SemanticVersion);
54 
55     static std::optional<SemanticVersion> parse(std::string_view data);
56 
57     std::string toString() const;
58 
59     FCITX_DECLARE_PROPERTY(uint32_t, major, setMajor);
60     FCITX_DECLARE_PROPERTY(uint32_t, minor, setMinor);
61     FCITX_DECLARE_PROPERTY(uint32_t, patch, setPatch);
62     FCITX_DECLARE_PROPERTY(std::vector<PreReleaseId>, preReleaseIds,
63                            setPreReleaseIds);
64     FCITX_DECLARE_PROPERTY(std::vector<std::string>, buildIds, setBuildIds);
65     bool isPreRelease() const;
66 
67     int compare(const SemanticVersion &version) const noexcept;
68 
69 private:
70     uint32_t major_ = 0;
71     uint32_t minor_ = 1;
72     uint32_t patch_ = 0;
73     std::vector<PreReleaseId> preReleaseIds_;
74     std::vector<std::string> buildIds_;
75 };
76 
77 inline bool operator<(const PreReleaseId &lhs,
78                       const PreReleaseId &rhs) noexcept {
79     return lhs.compare(rhs) < 0;
80 }
81 
82 inline bool operator>(const PreReleaseId &lhs,
83                       const PreReleaseId &rhs) noexcept {
84     return rhs < lhs;
85 }
86 
87 inline bool operator==(const PreReleaseId &lhs,
88                        const PreReleaseId &rhs) noexcept {
89     return lhs.compare(rhs) == 0;
90 }
91 
92 inline bool operator!=(const PreReleaseId &lhs,
93                        const PreReleaseId &rhs) noexcept {
94     return !(lhs == rhs);
95 }
96 
97 inline bool operator<=(const PreReleaseId &lhs,
98                        const PreReleaseId &rhs) noexcept {
99     return !(lhs > rhs);
100 }
101 
102 inline bool operator>=(const PreReleaseId &lhs,
103                        const PreReleaseId &rhs) noexcept {
104     return !(lhs < rhs);
105 }
106 
107 inline bool operator<(const SemanticVersion &lhs,
108                       const SemanticVersion &rhs) noexcept {
109     return lhs.compare(rhs) < 0;
110 }
111 
112 inline bool operator>(const SemanticVersion &lhs,
113                       const SemanticVersion &rhs) noexcept {
114     return rhs < lhs;
115 }
116 
117 inline bool operator==(const SemanticVersion &lhs,
118                        const SemanticVersion &rhs) noexcept {
119     return lhs.compare(rhs) == 0;
120 }
121 
122 inline bool operator!=(const SemanticVersion &lhs,
123                        const SemanticVersion &rhs) noexcept {
124     return !(lhs == rhs);
125 }
126 
127 inline bool operator<=(const SemanticVersion &lhs,
128                        const SemanticVersion &rhs) noexcept {
129     return !(lhs > rhs);
130 }
131 
132 inline bool operator>=(const SemanticVersion &lhs,
133                        const SemanticVersion &rhs) noexcept {
134     return !(lhs < rhs);
135 }
136 
137 inline LogMessageBuilder &operator<<(LogMessageBuilder &builder,
138                                      const SemanticVersion &version) {
139     builder << "SemanticVersion(" << version.toString() << ")";
140     return builder;
141 }
142 
143 } // namespace fcitx
144 
145 #endif // _FCITX_UTILS_SEMVER_H_
146