Semantic Versioning for modern C++

Overview
         _____                            _   _
        / ____|                          | | (_)
       | (___   ___ _ __ ___   __ _ _ __ | |_ _  ___
        \___ \ / _ \ '_ ` _ \ / _` | '_ \| __| |/ __|
        ____) |  __/ | | | | | (_| | | | | |_| | (__
       |_____/ \___|_| |_| |_|\__,_|_| |_|\__|_|\___|
__      __           _             _                _____
\ \    / /          (_)           (_)              / ____|_     _
 \ \  / /__ _ __ ___ _  ___  _ __  _ _ __   __ _  | |   _| |_ _| |_
  \ \/ / _ \ '__/ __| |/ _ \| '_ \| | '_ \ / _` | | |  |_   _|_   _|
   \  /  __/ |  \__ \ | (_) | | | | | | | | (_| | | |____|_|   |_|
    \/ \___|_|  |___/_|\___/|_| |_|_|_| |_|\__, |  \_____|
                                            __/ |
                                           |___/

Github releases Vcpkg package Conan package License

C++ library compare and manipulate versions are available as extensions to the <major>.<minor>.<patch>-<prerelease_type>.<prerelease_number> format complying with Semantic Versioning 2.0.0

Features

  • C++17
  • Header-only
  • Dependency-free
  • Constexpr comparison: <, <=, ==, !=, > >=
  • Constexpr from string
  • Constexpr to string
  • Constexpr range matching

Examples

  • Create

    constexpr version v1 = version{1, 2, 3, prerelease::rc, 4};
    constexpr version v2 = v1;
  • Сomparison

    constexpr semver::version v1{1, 4, 3};
    constexpr semver::version v2{1, 2, 4, semver::prerelease::alpha, 10};
    static_assert(v1 != v2);
    static_assert(v1 > v2);
    static_assert(v1 >= v2);
    static_assert(v2 < v1);
    static_assert(v2 <= v1);
  • To string

    semver::version v{1, 2, 3, prerelease::rc, 4};
    
    // To string.
    std::string s1 = v.to_string(); // may throw.
    
    // Non-member to string.
    std::string s2 = semver::to_string(v); // may throw.
    
    std::array<char, 32> str = {};
    
    // constexpr to chars, like <https://en.cppreference.com/w/cpp/utility/to_chars>.
    auto [p, ec] = v.to_chars(str.data(), str.data() + str.size()); // constexpr and no throw.
    
    // Non-member constexpr to chars, like <https://en.cppreference.com/w/cpp/utility/to_chars>.
    auto [p, ec] = semver::to_chars(str.data(), str.data() + str.size(), v); // constexpr and no throw.
  • From string

    std::string_view s = "1.2.3-rc.4";
    
    // From chars.
    semver::version v1{s}; // constexpr and may throw.
    
    // User-defined literals '_version'.
    semver::version v2 = "1.2.3-rc.4"_version; // constexpr and may throw.
    
    // constexpr from_chars, like <https://en.cppreference.com/w/cpp/utility/from_chars>.
    semver::version v3;
    auto [p, ec] = v3.to_chars(str.data(), str.data() + str.size()); // constexpr and no throw.
    
    // Non-member constexpr from chars, like <https://en.cppreference.com/w/cpp/utility/from_chars>.
    semver::version v4;
    auto [p, ec] = semver::to_chars(str.data(), str.data() + str.size(), v4); // constexpr and no throw.
    
    // Non-member from string.
    semver::version v5 = semver::from_string(s); // constexpr and may throw.
    std::optional<version> v6 = semver::from_string_noexcept(s); // constexpr and no throw.
    
    // From string.
    semver::version v6;
    v7.from_string(s); // constexpr and may throw.
    bool success = v8.from_string_noexcept(s); // constexpr and no throw.
  • Range matching

    constexpr auto range = semver::range(">=1.0.0 <2.0.0 || >3.2.1");
    constexpr auto version = semver::version("1.2.3");
    if (range.satisfies(version)) {
      // Do something.
    }
  • Range matching with prerelease tag

    constexpr auto range = semver::range(">1.2.3-beta.1");
    constexpr auto version = semver::version("3.4.5-alpha.0");
    
    // By default, version is allowed to satisfy range if at least one comparator with the same [major, minor, patch] has a prerelease tag.
    static_assert(!range.satisfies(version));
    // Suppress this behavior and treat prerelease versions as normal.
    static_assert(range.satisfies(version, semver::range::option::include_prerelease));

Integration

You should add required file semver.hpp.

If you are using vcpkg on your project for external dependencies, then you can use the neargye-semver.

If you are using Conan to manage your dependencies, merely add neargye-semver/x.y.z to your conan's requires, where x.y.z is the release version you want to use.

Alternatively, you can use something like CPM which is based on CMake's Fetch_Content module.

CPMAddPackage(
    NAME semver
    GITHUB_REPOSITORY Neargye/semver
    GIT_TAG x.y.z # Where `x.y.z` is the release version you want to use.
)

Compiler compatibility

  • Clang/LLVM >= 5
  • MSVC++ >= 14.11 / Visual Studio >= 2017
  • Xcode >= 10
  • GCC >= 7

Licensed under the MIT License

Comments
  • from_string() `invalid argument` exception

    from_string() `invalid argument` exception

    Hi, I am trying to use from_string(). I am also using Qt.

    Below code works fine: semver::version version_in_db = semver::from_string(QString("1.0.0").toStdString());

    But the below code fails with an exeption of 'invalid argument': semver::version version_in_db = semver::from_string(QString("1.0.0-beta").toStdString());

    Adding the '-beta' seems to be causing it to fail.

    bug 
    opened by juliendz 5
  • Support prerelease with no number

    Support prerelease with no number

    According to semver, prerelease tags can have lots more content than just [alpha/beta/rc].#. While more work is required to support this, this PR adds the ability to specify a numberless prerelease range. Prerelease versions will also respect this (previously, 1.2.3-alpha implied 1.2.3-alpha.0).

    Comparatively, 1.2.3-alpha comes before 1.2.3-alpha.0 based on most other implementations.

    opened by TylerJang27 2
  • Check for beta-updates

    Check for beta-updates

    Hi, is there an option to check for new beta versions as well? When comparing 0.10.0-beta.2 > 0.10.0-beta.1, the result will be FALSE. I'd also like to check if the beta version increased.

    Best regards Axel

    opened by Clamb94 2
  • Adding semver to vcpkg

    Adding semver to vcpkg

    Hi! I created a pull request to the vcpkg repository adding support for your library that you can see here: microsoft/vcpkg#12406. Alas, maintainers requested that the name in vcpkg be changed to something more specific than semver which they deemed to generic given the unestabilished status of the library.

    Do you have any other preferences or should we go with the proposed Neargye-semver?

    enhancement 
    opened by Vennor 2
  • Fix typo in name of library version constant

    Fix typo in name of library version constant

    Hello again, I noticed that the constant defining the version of the semver library itself contained a typo (semver_verion instead of semver_version). Changing this would of course technically break code using the old name, but I don't think there are many projects that would actually be affected by this, so it should be fine.

    opened by liliolett 1
  • Fix semver.org link in readme

    Fix semver.org link in readme

    Hi, I stumbled upon your project and noticed that the link to semver.org in the readme was missing the protocol which caused it be interpreted as referring to a local file instead of a website. This is now fixed.

    opened by liliolett 1
  • Improve to/from string

    Improve to/from string

    • [x] constexpr from_chars
    • [x] constexpr to_chars
    • [x] inline to_string
    • [x] constexpr from_string
    • [x] template operator<< ~~template operator>>~~
    enhancement 
    opened by Neargye 1
  • constexpr function never produces a constant expression

    constexpr function never produces a constant expression

    Hello,

    Thanks for your nice library. Trying to compile it with clang 6.0.1 results on compiler error : constexpr function never produces a constant expression

    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:513:26: error: constexpr function never produces a constant expression [-Winvalid-constexpr]
        auto is_logical_or = [&parser]() constexpr noexcept -> bool { return parser.current_token.type == range_token_type::logical_or; };
                             ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:513:74: note: read of non-constexpr variable 'parser' is not allowed in a constant expression
        auto is_logical_or = [&parser]() constexpr noexcept -> bool { return parser.current_token.type == range_token_type::logical_or; };
                                                                             ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:511:18: note: declared here
        range_parser parser{str_};
                     ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:515:24: error: constexpr function never produces a constant expression [-Winvalid-constexpr]
        auto is_operator = [&parser]() constexpr noexcept -> bool { return parser.current_token.type == range_token_type::range_operator; };
                           ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:515:72: note: read of non-constexpr variable 'parser' is not allowed in a constant expression
        auto is_operator = [&parser]() constexpr noexcept -> bool { return parser.current_token.type == range_token_type::range_operator; };
                                                                           ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:511:18: note: declared here
        range_parser parser{str_};
                     ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:517:22: error: constexpr function never produces a constant expression [-Winvalid-constexpr]
        auto is_number = [&parser]() constexpr noexcept -> bool { return parser.current_token.type == range_token_type::number; };
                         ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:517:70: note: read of non-constexpr variable 'parser' is not allowed in a constant expression
        auto is_number = [&parser]() constexpr noexcept -> bool { return parser.current_token.type == range_token_type::number; };
                                                                         ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:511:18: note: declared here
        range_parser parser{str_};
                     ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:581:9: warning: default label in switch which covers all enumeration values [-Wcovered-switch-default]
            default:
            ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:609:53: warning: constructor parameter 'text' shadows the field 'text' of 'range_lexer' [-Wshadow-field-in-constructor]
        constexpr explicit range_lexer(std::string_view text) noexcept : text{text}, pos{0} {}
                                                        ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:606:22: note: previous declaration is here
        std::string_view text;
                         ^
    /home/runner/work/YAODAQ/YAODAQ/build/_deps/semver-src/include/semver.hpp:794:3: warning: default label in switch which covers all enumeration values [-Wcovered-switch-default]
      default:
    
    opened by flagarde 0
  • Add badge and info about conan package

    Add badge and info about conan package

    Hello, I really missed Conan package for your lib, so I've made one and it's in the conan-center repo now. This PR adds the badge and info about it (not sure about the color).

    opened by i-vovk 0
  • [Feature] Semver Ranges

    [Feature] Semver Ranges

    [Work in progress]

    It's a draft implementation of semver ranges. It's already supports basic range comparators like

    • >=1.2.7
    • >=1.2.0 <=2.3.4

    Example

    const semver::range range(">= 1.2.4 < 2.0.0");
    constexpr semver::version version = "1.5.2"_version;
    if (range.contains(version)) {
      // do something
    }
    

    What I'm going to do next:

    • support prerelease tags
    • support range set chaining by ||
    • support advanced range syntax (hyphen, caret, tilde, etc)
    • make it constexpr if possible

    Any suggestions and improvements are welcome.

    opened by Naratzul 0
  • 5.99.999 is valid occurding to semver.org but does not parse

    5.99.999 is valid occurding to semver.org but does not parse

    Hi,

    I think I found a bug.

    5.99.999 is valid occurding to semver.org but does not parse:

    auto v = semver::from_string("5.99.999");
    

    I get an exception:

    C++ exception with description "semver::version::from_string invalid version."
    
    opened by kp-cat 1
  • Limitation to `std::uint8_t` might yield an overflow for some projects

    Limitation to `std::uint8_t` might yield an overflow for some projects

    opened by daixtrose 1
  • Exception in parsing

    Exception in parsing "1.37.0-1"

    Nice header-only project, but unfortunately not usable for me, because the following code throws an exeption (semver::version::from_string invalid version).

    semver::version vNew = semver::from_string("1.37.0-1");
    

    According to semver.org, this is a valid version with "pre-release" tag.

    opened by tirolerstefan 0
  • feature request: from_string accepts incomplete version strings

    feature request: from_string accepts incomplete version strings

    The test

    TEST_CASE("semver::from_string", "[demo]")
    {
        using namespace semver;
        // auto version = semver::from_string("1.0.0"); // SUCCEEDS
        auto version = semver::from_string("1.0"); // FAILS
        REQUIRE(version == "1.0.0"_version);
    }
    

    fails with an exception

    semver::version::from_string invalid version.

    It is quite common to omit the patch version. So the from_string/from_chars function pair should be robust against the omission and add .0.

    opened by daixtrose 1
  • Build Metadata

    Build Metadata

    Hi @Neargye,

    thanks for implementing semver! We've been using it in our project since version 0.1.8, but had to add the build metadata ourselves. It would be nice if you could add this also to the official repo.

    https://semver.org/#spec-item-10

    We use it to store and compare the build hash.

    Example: 1.4.0-alpha.1+6703c608

    enhancement 
    opened by dFohlen 0
Releases(v0.3.0)
Owner
Daniil Goncharov
Daniil Goncharov
C/C++ language server supporting multi-million line code base, powered by libclang. Emacs, Vim, VSCode, and others with language server protocol support. Cross references, completion, diagnostics, semantic highlighting and more

Archived cquery is no longer under development. clangd and ccls are both good replacements. cquery cquery is a highly-scalable, low-latency language s

Jacob Dufault 2.3k Nov 20, 2022
C/C++/ObjC language server supporting cross references, hierarchies, completion and semantic highlighting

ccls ccls, which originates from cquery, is a C/C++/Objective-C language server. code completion (with both signature help and snippets) definition/re

Fangrui Song 3.2k Nov 23, 2022
weggli is a fast and robust semantic search tool for C and C++ codebases. It is designed to help security researchers identify interesting functionality in large codebases.

weggli is a fast and robust semantic search tool for C and C++ codebases. It is designed to help security researchers identify interesting functionality in large codebases.

Google Project Zero 2k Dec 1, 2022
Semantic Edge Detection with Diverse Deep Supervision

Semantic Edge Detection with Diverse Deep Supervision This repository contains the code for our IJCV paper: "Semantic Edge Detection with Diverse Deep

Yun Liu 13 Oct 7, 2022
BAAF-Net - Semantic Segmentation for Real Point Cloud Scenes via Bilateral Augmentation and Adaptive Fusion (CVPR 2021)

Semantic Segmentation for Real Point Cloud Scenes via Bilateral Augmentation and Adaptive Fusion (CVPR 2021) This repository is for BAAF-Net introduce

null 89 Nov 8, 2022
C parsing, semantic analys, generate a graph from a source code. An educational project during my third year of Computer Science Licence.

Pour compiler le programme, il suffit d'exécuter compiler.sh avec la commande "./compiler.sh" en se trouvant dans le dossier racine du projet. Un fich

Jean Philippe Carlens 3 Feb 3, 2022
Pretty Printer for Modern C++

Highlights Single header file Requires C++17 MIT License Quick Start Simply include pprint.hpp and you're good to go. #include <pprint.hpp> To start p

Pranav 880 Nov 23, 2022
Gaming meets modern C++ - a fast and reliable entity component system (ECS) and much more

EnTT is a header-only, tiny and easy to use library for game programming and much more written in modern C++. Among others, it's used in Minecraft by

Michele Caini 7.4k Nov 29, 2022
Nameof operator for modern C++, simply obtain the name of a variable, type, function, macro, and enum

_ _ __ _____ | \ | | / _| / ____|_ _ | \| | __ _ _ __ ___ ___ ___ | |_ | | _| |

Daniil Goncharov 1.5k Nov 25, 2022
Random for modern C++ with convenient API

Random for modern C++ with convenient API Design goals Supported compilers Integration Five-minute tutorial Number range Common type number range Char

Ilya Polishchuk 732 Nov 26, 2022
A Minimal, Header only Modern c++ library for terminal goodies 💄✨

rang Colors for your Terminal. Windows Demo Example usage #include "rang.hpp" using namespace std; using namespace rang; int main() { cout << "P

Abhinav Gauniyal 1.3k Nov 28, 2022
A modern C++ tweening library

Tweeny Tweeny is an inbetweening library designed for the creation of complex animations for games and other beautiful interactive software. It levera

Leonardo Guilherme de Freitas 573 Nov 23, 2022
Activity Indicators for Modern C++

Highlights Thread-safe progress bars and spinners Header-only library. Grab a copy of include/indicators. Single-header version in single_include/indi

Pranav 2.2k Nov 27, 2022
Table Maker for Modern C++

Source for the above image can be found here Table of Contents Quick Start Formatting Options Style Inheritance Model Word Wrapping Font Alignment Fon

Pranav 1.4k Nov 22, 2022
🏢 A bold, unapologetic, and honest operating system written in modern C

A bold, unapologetic, and honest operating system written in modern C About Striking modernist shapes and bold use of modern C are the hallmarks of BR

Brutal 917 Nov 30, 2022
🏢 An operating system that combine the desire of UNIX utopia from the 1970s with modern technology and engineering

Striking modernist shapes and bold use of modern C are the hallmarks of BRUTAL. BRUTAL combine the desire of UNIX utopia from the 1970s with modern te

Brutal 910 Nov 23, 2022
"Sigma File Manager" is a free, open-source, quickly evolving, modern file manager (explorer / finder) app for Windows, MacOS, and Linux.

"Sigma File Manager" is a free, open-source, quickly evolving, modern file manager (explorer / finder) app for Windows, MacOS, and Linux.

Aleksey Hoffman 1k Dec 1, 2022
Ceres is designed to be a modern and minimalistic C like language.

Ceres v0.0.1 Ceres is designed to be a modern and minimalistic C like language. For now, it will be interpreted but later on I do want to write a comp

null 9 May 18, 2022