Skip to content

z4kn4fein/cpp-semver

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

53 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

cpp-semver

Build Build codecov vcpkg godbolt

Semantic Versioning library for modern C++. It implements the full semantic version 2.0.0 specification and provides the ability to parse, compare, and increment semantic versions.

Features

  • C++17
  • Single-file / header-only
  • No external dependencies

Installation

  1. Include semver.hpp

    As semver is a header-only library, you can download and copy semver.hpp to your project's include path.

  2. With cmake

    include(FetchContent)
    
    FetchContent_Declare(
        cpp-semver
        GIT_REPOSITORY https://github.com/z4kn4fein/cpp-semver.git
        GIT_TAG v0.3.3)
    FetchContent_MakeAvailable(cpp-semver)

    This will produce the target semver which you can link against the typical way:

    target_link_libraries(your_target_name PRIVATE semver)
  3. With vcpkg

    If you are using vcpkg for external dependencies, then you can install the package with:

    vcpkg install z4kn4fein-semver

Usage

The following options are available to construct a version:

  1. Building part by part.

    auto version = semver::version(3, 5, 2, "alpha", "build");
  2. Parsing from a string with semver::version::parse():

    auto version = semver::version::parse("3.5.2-alpha+build");
  3. Using the _v user-defined literal on a string.

    using namespace semver::literals; // required to use the literals
    
    auto version = "3.5.2-alpha+build"_v;

The constructed version provides the following information:

semver::version version = "3.5.2-alpha.2+build"_v;

std::cout << version;                     // 3.5.2-alpha.2+build
std::cout << version.major();             // 3
std::cout << version.minor();             // 5
std::cout << version.patch();             // 2
std::cout << version.prerelease();        // "alpha.2"
std::cout << version.build_meta();        // "build"

std::cout << version.is_prerelease();     // true
std::cout << version.is_stable();         // false

std::cout << version.without_suffixes();  // "3.5.2"

Strict vs. Loose Parsing

By default, the version parser considers partial versions like 1.0 and versions starting with the v prefix invalid. This behaviour can be turned off by setting the parser's strict parameter to false or by using the _lv user-defined literal.

std::cout << "v2.3-alpha"_v;                                  // exception
std::cout << "2.1"_v;                                         // exception
std::cout << "v3"_v;                                          // exception

std::cout << semver::version::parse("v2.3-alpha", false);     // 2.3.0-alpha
std::cout << "2.1"_lv;                                        // 2.1.0
std::cout << "v3"_lv;                                         // 3.0.0

Compare

It is possible to compare two version objects with comparison operators.

"0.1.0"_v < "0.1.1"_v;                   // true
"0.1.1"_v <= "0.1.1"_v;                  // true
"0.1.0-alpha.3"_v < "0.1.0-alpha.4"_v;   // true

The equality of two version objects can be determined with equality operators.

"0.1.1"_v == "0.1.1"_v;       // true
"0.1.1"_v != "0.1.1"_v;       // false

Increment

version objects can produce incremented versions of themselves with the next_major(), next_minor(), next_patch(), next_prerelease(), and increment() methods. These methods can be used to determine the next version in order by increasing the appropriate identifier. version objects are immutable, so each incrementing function creates a new version.

This example shows how the incrementation works on a stable version:

auto stable = "1.0.0"_v;

std::cout << stable.next_major();                          // 2.0.0
std::cout << stable.next_minor();                          // 1.1.0
std::cout << stable.next_patch();                          // 1.0.1
std::cout << stable.next_prerelease();                     // 1.0.1-0

// or with the increment() method:
std::cout << stable.increment(semver::inc::major);         // 2.0.0
std::cout << stable.increment(semver::inc::minor);         // 1.1.0
std::cout << stable.increment(semver::inc::patch);         // 1.0.1
std::cout << stable.increment(semver::inc::prerelease);    // 1.0.1-0

In case of an unstable version:

auto unstable = "1.0.0-alpha.2+build.1"_v;

std::cout << unstable.next_major();                         // 2.0.0
std::cout << unstable.next_minor();                         // 1.1.0
std::cout << unstable.next_patch();                         // 1.0.0
std::cout << unstable.next_prerelease();                    // 1.0.0-alpha.3

// or with the increment() method:
std::cout << unstable.increment(semver::inc::major);        // 2.0.0
std::cout << unstable.increment(semver::inc::minor);        // 1.1.0
std::cout << unstable.increment(semver::inc::patch);        // 1.0.0
std::cout << unstable.increment(semver::inc::prerelease);   // 1.0.0-alpha.3

Each incrementing function provides the option to set a pre-release identity on the incremented version.

auto version = "1.0.0-alpha.1"_v;

std::cout << version.next_major("beta");                            // 2.0.0-beta
std::cout << version.next_minor("");                                // 1.1.0
std::cout << version.next_patch("alpha");                           // 1.0.1-alpha
std::cout << version.next_prerelease("alpha");                      // 1.0.0-alpha.2

// or with the increment() method:
std::cout << version.increment(semver::inc::major, "beta");         // 2.0.0-beta
std::cout << version.increment(semver::inc::minor, "");             // 1.1.0
std::cout << version.increment(semver::inc::patch, "alpha");        // 1.0.1-alpha
std::cout << version.increment(semver::inc::prerelease, "alpha");   // 1.0.0-alpha.2

Exceptions

When the version parsing fails due to an invalid format, the library throws a specific semver_exception.

Contact & Support

  • Create an issue for bug reports and feature requests.
  • Start a discussion for your questions and ideas.
  • Add a ⭐️ to support the project!