| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | //================================================================================================== | ||
| 2 | /* | ||
| 3 | SPY - C++ Informations Broker | ||
| 4 | Copyright : SPY Project Contributors | ||
| 5 | SPDX-License-Identifier: BSL-1.0 | ||
| 6 | */ | ||
| 7 | //================================================================================================== | ||
| 8 | #pragma once | ||
| 9 | |||
| 10 | #include <compare> | ||
| 11 | |||
| 12 | namespace spy::_ | ||
| 13 | { | ||
| 14 | template<typename T> | ||
| 15 | concept stream = requires(T& os, char c) { | ||
| 16 | { os.copyfmt(os) }; | ||
| 17 | { os.flush() }; | ||
| 18 | { os.put(c) }; | ||
| 19 | }; | ||
| 20 | |||
| 21 | template<char... c> constexpr int find(int i0) | ||
| 22 | { | ||
| 23 | int sz = sizeof...(c); | ||
| 24 | char arr[] = {c...}; | ||
| 25 | while(i0 < sz && arr[ i0 ] != '\'') ++i0; | ||
| 26 | return i0; | ||
| 27 | } | ||
| 28 | |||
| 29 | template<char... c> constexpr int parse(int i0, int i1) | ||
| 30 | { | ||
| 31 | char arr[] = {c...}; | ||
| 32 | int value = 0; | ||
| 33 | while(i0 < i1 && arr[ i0 ] != '\'') value = value * 10 + (arr[ i0++ ] - 48); | ||
| 34 | return value; | ||
| 35 | } | ||
| 36 | |||
| 37 | template<template<int, int, int> class Wrapper, char... c> constexpr auto literal_wrap() | ||
| 38 | { | ||
| 39 | constexpr int b0 = 0, e0 = find<c...>(0); | ||
| 40 | constexpr int b1 = e0 + 1, e1 = find<c...>(b1); | ||
| 41 | constexpr int b2 = e1 + 1, e2 = sizeof...(c); | ||
| 42 | |||
| 43 | return Wrapper<parse<c...>(b0, e0), parse<c...>(b1, e1), parse<c...>(b2, e2)> {}; | ||
| 44 | } | ||
| 45 | |||
| 46 | template<int M, int N, int P> struct version_id | ||
| 47 | { | ||
| 48 | static constexpr int major = M; | ||
| 49 | static constexpr int minor = N; | ||
| 50 | static constexpr int patch = P; | ||
| 51 | }; | ||
| 52 | |||
| 53 | template<int M1, int N1, int P1, int M2, int N2, int P2> | ||
| 54 | constexpr bool operator==(version_id<M1, N1, P1>, version_id<M2, N2, P2>) noexcept | ||
| 55 | { | ||
| 56 | return (M1 == M2) && (N1 == N2) && (P1 == P2); | ||
| 57 | } | ||
| 58 | |||
| 59 | template<int M1, int N1, int P1, int M2, int N2, int P2> | ||
| 60 | constexpr std::strong_ordering operator<=>(version_id<M1, N1, P1>, | ||
| 61 | version_id<M2, N2, P2>) noexcept | ||
| 62 | { | ||
| 63 | if constexpr(constexpr auto cmp0 = M1 <=> M2; cmp0 != 0) return cmp0; | ||
| 64 | else if constexpr(constexpr auto cmp1 = N1 <=> N2; cmp1 != 0) return cmp1; | ||
| 65 | else return P1 <=> P2; | ||
| 66 | } | ||
| 67 | |||
| 68 | template<int M = 1, int N = 0, int P = 0> constexpr inline version_id<M, N, P> version = {}; | ||
| 69 | |||
| 70 | using unspecified_version_t = version_id<-1, 0, 0>; | ||
| 71 | constexpr inline unspecified_version_t unspecified_version = {}; | ||
| 72 | |||
| 73 | 3 | template<_::stream OS, int M, int N, int P> auto& operator<<(OS& os, version_id<M, N, P> const&) | |
| 74 | { | ||
| 75 | 3 | return os << "v" << M << "." << N << "." << P; | |
| 76 | } | ||
| 77 | |||
| 78 | template<_::stream OS> auto& operator<<(OS& os, unspecified_version_t const&) | ||
| 79 | { | ||
| 80 | return os << "(unspecified)"; | ||
| 81 | } | ||
| 82 | } | ||
| 83 |