1 // Copyright 2015 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #pragma once
16
17 #include <string>
18 #include <string_view>
19 #include <tuple>
20
21 namespace android {
22 namespace base {
23
24 // Class |Version| is a class for software version manipulations
25 // it is able to parse, store, compare and convert version back to string
26 // Expected string format is "major.minor.micro[.build]", where all
27 // components are unsigned numbers (and, hopefully, reasonably small)
28 class Version {
29 public:
30 enum Component { kMajor, kMinor, kMicro, kBuild };
31
32 using ComponentType = unsigned int;
33
34 // This is the value for an invalid/missing version component.
35 static constexpr ComponentType kNone = static_cast<ComponentType>(-1);
36
37 explicit Version(const char* ver);
Version(const std::string & ver)38 explicit Version(const std::string& ver) : Version(ver.data()) {}
39
40 constexpr Version();
41
42 constexpr Version(ComponentType major,
43 ComponentType minor,
44 ComponentType micro,
45 ComponentType build = 0);
46
47 constexpr bool isValid() const;
48
49 constexpr bool operator<(const Version& other) const;
50 constexpr bool operator>(const Version& other) const;
51 constexpr bool operator==(const Version& other) const;
52 constexpr bool operator!=(const Version& other) const;
53
54 static constexpr Version invalid();
55
56 std::string toString() const;
57
58 template <Component C>
component()59 constexpr ComponentType component() const {
60 return std::get<static_cast<size_t>(C)>(mData);
61 }
62
63 private:
64 ComponentType& component(Component c);
65
66 private:
67 static const int kComponentCount = kBuild + 1;
68
69 std::tuple<ComponentType, ComponentType, ComponentType, ComponentType>
70 mData;
71 };
72
73 // all constexpr functions have to be defined in the header, just like templates
74
Version()75 constexpr Version::Version() : Version(kNone, kNone, kNone) {}
76
Version(ComponentType major,ComponentType minor,ComponentType micro,ComponentType build)77 constexpr Version::Version(ComponentType major,
78 ComponentType minor,
79 ComponentType micro,
80 ComponentType build)
81 : mData(major, minor, micro, build) {}
82
isValid()83 constexpr bool Version::isValid() const {
84 return *this != invalid();
85 }
86
87 constexpr bool Version::operator<(const Version& other) const {
88 return mData < other.mData;
89 }
90
91 constexpr bool Version::operator>(const Version& other) const {
92 return mData > other.mData;
93 }
94
95 constexpr bool Version::operator==(const Version& other) const {
96 return mData == other.mData;
97 }
98
99 constexpr bool Version::operator!=(const Version& other) const {
100 return !(*this == other);
101 }
102
invalid()103 constexpr Version Version::invalid() {
104 return Version(kNone, kNone, kNone);
105 }
106
107 } // namespace android
108 } // namespace base
109