aboutsummaryrefslogtreecommitdiffstats
path: root/vespalib/src/vespa/vespalib/component/version.h
blob: 78dd01819af79a3ae4e4fced84560d72dbb8397a (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
// Copyright Vespa.ai. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
#pragma once

#include <vespa/vespalib/stllike/string.h>

namespace vespalib {

/**
 * @brief A component version identifier.
 *
 * Version identifiers have four components.
 * <ol>
 * <li>Major version. A non-negative integer.</li>
 * <li>Minor version. A non-negative integer.</li>
 * <li>Micro version. A non-negative integer.</li>
 * <li>Qualifier. An ascii text string. See <code>Version(String)</code> for the
 * format of the qualifier string.</li>
 * </ol>
 * <p>
 * An unspecified component is equivalent to 0 (or the empty string for qualifier).<br>
 * <p>
 * <code>Version</code> objects are immutable.
 *
 * @author arnej27959
 * @author bratseth
 **/
class Version
{
public:
    using string = vespalib::string;
private:
    int _major;
    int _minor;
    int _micro;
    string _qualifier;
    string _stringValue;

    /**
     * Must be called on construction after the component values are set.
     * Creates the underlying version string, and verifies that values are sound.
     */
    void initialize();
    /**
     * Is called after initialization if there are problems.
     * @throws IllegalArgumentException If the numerical components are negative
     *         or the qualifier string is invalid.
     */
    void verifySanity() __attribute__((noinline));

public:
    /**
     * @brief Creates a version identifier from the specified components.
     *
     * @param major major component of the version identifier, 0 if not specified
     * @param minor minor component of the version identifier, 0 if not specified
     * @param micro micro component of the version identifier, 0 if not specified
     * @param qualifier Qualifier component of the version identifier, empty string if unspecified
     * @throws IllegalArgumentException if the numerical components are negative
     *         the qualifier string contains non-word/digit-characters
     */

    Version(int major = 0, int minor = 0, int micro = 0, const string & qualifier = "");
    Version(const Version &);
    Version & operator = (const Version &);
    ~Version();

    /**
     * @brief Creates a version identifier from the specified string.
     *
     * Version strings follows this grammar (same as Osgi versions):
     *
     * <pre>
     * version ::= major('.'minor('.'micro('.'qualifier)?)?)?
     * major ::= digit+
     * minor ::= digit+
     * micro ::= digit+
     * qualifier ::= (alpha|digit|'_'|'-')+
     * digit ::= [0..9]
     * alpha ::= [a..zA..Z]
     * </pre>
     *
     * @param versionString String representation of the version identifier
     * @throws IllegalArgumentException If <code>version</code> is improperly
     *         formatted.
     */
    Version(const string & versionString);

    /** @brief Returns the major component of this version, or 0 if not specified */
    int getMajor() const { return _major; }

    /** @brief Returns the minor component of this version, or 0 if not specified */
    int getMinor() const { return _minor; }

    /** @brief Returns the micro component of this version, or 0 if not specified */
    int getMicro() const { return _micro; }

    /** @brief Returns the qualifier component of this version, or "" if not specified */
    const string &  getQualifier() const { return _qualifier; }

    /**
     * @brief Returns the string representation of this version identifier as major.minor.micro,
     * or major.minor.micro.qualifier if a non-empty qualifier was specified.
     */
    const string & toString() const { return _stringValue; }

    /**
     * @brief Compares this Version object to another.
     *
     * A version is considered to be <b>equal to </b> another version if the
     * major, minor and micro components are equal and the qualifier component
     * has the same value.
     *
     * @param other The <code>Version</code> object to be compared.
     * @return true if equal, false otherwise
     */
    bool equals(const Version& other) const;
    bool operator==(const Version& other) const { return equals(other); }

    /**
     * @brief Compares this Version object to another.
     *
     * A version is considered to be <b>less than </b> another version if its
     * major component is less than the other version's major component, or the
     * major components are equal and its minor component is less than the other
     * version's minor component, or the major and minor components are equal
     * and its micro component is less than the other version's micro component,
     * or the major, minor and micro components are equal and it's qualifier
     * component is less than the other version's qualifier component (using
     * <code>string.compare</code>).
     *
     * A version is considered to be <b>equal to</b> another version
     * if the major, minor and micro components are equal and the
     * qualifier component has the same string value.
     *
     * @param other the <code>Version</code> object compared.
     * @return A negative integer, zero, or a positive integer if this object is
     *         less than, equal to, or greater than the specified <code>Version</code> object.
     * @throws ClassCastException if the specified object is not a <code>Version</code>.
     */
    int compareTo(const Version& other) const;
    bool operator<(const Version& other) const { return compareTo(other) < 0; }

};

} // namespace vespalib