| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| #pragma once |
| |
| #include <cstdint> |
| #include <iomanip> |
| #include <istream> |
| #include <ostream> |
| |
| namespace ignite { |
| |
| /** |
| * @brief Universally unique identifier (UUID). |
| * |
| * Minimalistic implementation that mimics JDK java.util.UUID. |
| */ |
| class uuid { |
| public: |
| /** |
| * Default constructor. |
| */ |
| constexpr uuid() noexcept = default; |
| |
| /** |
| * Constructor. |
| * |
| * @param most Most significant bits. |
| * @param least Least significant bits. |
| */ |
| constexpr uuid(std::int64_t most, std::int64_t least) noexcept |
| : most(most) |
| , least(least) {} |
| |
| /** |
| * Make random UUID. |
| * |
| * @return Randomly generated UUID instance. |
| */ |
| [[nodiscard]] static uuid random(); |
| |
| /** |
| * Returns the most significant 64 bits of this instance. |
| * |
| * @return The most significant 64 bits of this instance. |
| */ |
| [[nodiscard]] constexpr std::int64_t get_most_significant_bits() const noexcept { return most; } |
| |
| /** |
| * Returns the least significant 64 bits of this instance. |
| * |
| * @return The least significant 64 bits of this instance. |
| */ |
| [[nodiscard]] constexpr std::int64_t get_least_significant_bits() const noexcept { return least; } |
| |
| /** |
| * The version number associated with this instance. The version |
| * number describes how this uuid was generated. |
| * |
| * The version number has the following meaning: |
| * 1 Time-based UUID; |
| * 2 DCE security UUID; |
| * 3 Name-based UUID; |
| * 4 Randomly generated UUID. |
| * |
| * @return The version number of this instance. |
| */ |
| [[nodiscard]] constexpr std::int32_t version() const noexcept { |
| return static_cast<std::int32_t>((most >> 12) & 0x0f); |
| } |
| |
| /** |
| * The variant number associated with this instance. The variant |
| * number describes the layout of the uuid. |
| * |
| * The variant number has the following meaning: |
| * 0 Reserved for NCS backward compatibility; |
| * 2 IETF RFC 4122 (Leach-Salz), used by this class; |
| * 6 Reserved, Microsoft Corporation backward compatibility; |
| * 7 Reserved for future definition. |
| * |
| * @return The variant number of this instance. |
| */ |
| [[nodiscard]] constexpr std::int32_t variant() const noexcept { |
| auto least0 = static_cast<uint64_t>(least); |
| return static_cast<std::int32_t>((least0 >> (64 - (least0 >> 62))) & (least >> 63)); |
| } |
| |
| /** |
| * compare to another value. |
| * |
| * @param other Instance to compare to. |
| * @return Zero if equals, negative number if less, and positive if greater. |
| */ |
| [[nodiscard]] constexpr int compare(const uuid &other) const noexcept { |
| if (most != other.most) { |
| return most < other.most ? -1 : 1; |
| } |
| if (least != other.least) { |
| return least < other.least ? -1 : 1; |
| } |
| return 0; |
| } |
| |
| private: |
| /** Most significant bits. */ |
| std::int64_t most = 0; |
| |
| /** Least significant bits. */ |
| std::int64_t least = 0; |
| }; |
| |
| /** |
| * @brief Comparison operator. |
| * |
| * @param lhs First value. |
| * @param rhs Second value. |
| * @return true If the first value is equal to the second. |
| */ |
| constexpr bool operator==(const uuid &lhs, const uuid &rhs) noexcept { |
| return lhs.compare(rhs) == 0; |
| } |
| |
| /** |
| * @brief Comparison operator. |
| * |
| * @param lhs First value. |
| * @param rhs Second value. |
| * @return true If the first value is not equal to the second. |
| */ |
| constexpr bool operator!=(const uuid &lhs, const uuid &rhs) noexcept { |
| return lhs.compare(rhs) != 0; |
| } |
| |
| /** |
| * @brief Comparison operator. |
| * |
| * @param lhs First value. |
| * @param rhs Second value. |
| * @return true If the first value is less than the second. |
| */ |
| constexpr bool operator<(const uuid &lhs, const uuid &rhs) noexcept { |
| return lhs.compare(rhs) < 0; |
| } |
| |
| /** |
| * @brief Comparison operator. |
| * |
| * @param lhs First value. |
| * @param rhs Second value. |
| * @return true If the first value is less than or equal to the second. |
| */ |
| constexpr bool operator<=(const uuid &lhs, const uuid &rhs) noexcept { |
| return lhs.compare(rhs) <= 0; |
| } |
| |
| /** |
| * @brief Comparison operator. |
| * |
| * @param lhs First value. |
| * @param rhs Second value. |
| * @return true If the first value is greater than the second. |
| */ |
| constexpr bool operator>(const uuid &lhs, const uuid &rhs) noexcept { |
| return lhs.compare(rhs) > 0; |
| } |
| |
| /** |
| * @brief Comparison operator. |
| * |
| * @param lhs First value. |
| * @param rhs Second value. |
| * @return true If the first value is greater than or equal to the second. |
| */ |
| constexpr bool operator>=(const uuid &lhs, const uuid &rhs) noexcept { |
| return lhs.compare(rhs) >= 0; |
| } |
| |
| /** |
| * @brief Output operator. |
| * |
| * @param os Output stream. |
| * @param uuid Uuid to output. |
| * @return Reference to the first param. |
| */ |
| template<typename C, typename T> |
| ::std::basic_ostream<C, T> &operator<<(std::basic_ostream<C, T> &os, const uuid &uuid) { |
| auto msb = uuid.get_most_significant_bits(); |
| auto lsb = uuid.get_least_significant_bits(); |
| |
| auto part1 = static_cast<std::uint32_t>(msb >> 32); |
| auto part2 = static_cast<std::uint16_t>(msb >> 16); |
| auto part3 = static_cast<std::uint16_t>(msb); |
| auto part4 = static_cast<std::uint16_t>(lsb >> 48); |
| uint64_t part5 = lsb & 0x0000FFFFFFFFFFFFU; |
| |
| std::ios_base::fmtflags saved_flags = os.flags(); |
| |
| // clang-format off |
| os << std::hex |
| << std::setfill<C>('0') << std::setw(8) << part1 << '-' |
| << std::setfill<C>('0') << std::setw(4) << part2 << '-' |
| << std::setfill<C>('0') << std::setw(4) << part3 << '-' |
| << std::setfill<C>('0') << std::setw(4) << part4 << '-' |
| << std::setfill<C>('0') << std::setw(12) << part5; |
| // clang-format on |
| |
| os.flags(saved_flags); |
| |
| return os; |
| } |
| |
| /** |
| * Input operator. |
| * |
| * @param is Input stream. |
| * @param uuid Uuid to input. |
| * @return Reference to the first param. |
| */ |
| template<typename C, typename T> |
| ::std::basic_istream<C, T> &operator>>(std::basic_istream<C, T> &is, uuid &result) { |
| std::uint64_t parts[5]; |
| |
| std::ios_base::fmtflags saved_flags = is.flags(); |
| |
| is >> std::hex; |
| |
| for (int i = 0; i < 4; ++i) { |
| C delim; |
| |
| is >> parts[i] >> delim; |
| |
| if (delim != static_cast<C>('-')) { |
| return is; |
| } |
| } |
| |
| is >> parts[4]; |
| |
| is.flags(saved_flags); |
| |
| result = |
| uuid(std::int64_t((parts[0] << 32) | (parts[1] << 16) | parts[2]), std::int64_t((parts[3] << 48) | parts[4])); |
| |
| return is; |
| } |
| |
| } // namespace ignite |