From 638a0d1225b0950245c027d06834d20236455bfd Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Thu, 30 Mar 2023 12:14:09 -0400 Subject: [PATCH] src/cpp-common: improve C++ UUID utilities Philippe Proulx writing below. This patch improves the C++ common UUID utilities. Francis wrote the initial version of `bt2_common::Uuid`, and then we worked together to improve many little things at once, leading to this patch. His original message was: > Add `bt2_common::Uuid` > > This patch adds the `bt2_common::Uuid` class which represent UUIDs. > > `Uuid` instances can be created from byte array, strings, or > bt2_common::UuidView objects. > > The generate() static method returns a Uuid object with newly > generated UUID. > > The operator UuidView() method returns a bt2_common::UuidView object > representing the entire content of the UUID. > > The data() method returns a const pointer to the underlying > std::array<>. > > The str() method returns a new `std::string` instance containing the > canonical string representation of the UUID. The final improvements are: * Add said `bt2_common::Uuid` class. I also added the operator[](), operator=(), isNil(), begin(), and end() methods, the `Val` and `ConstIter` aliases, and the fact that most of the class relies on creating a `bt2_common::UuidView` to wrap itself when needed. data() just returns `const Val *`. * In `bt2_common::UuidView`: * Make the class `final`. * Add the `Val` and `ConstIter` aliases. * Add operator<(): makes it possible to use a `bt2_common::UuidView` as an `std::set` value type or as an `std::map` key type, and to use it with STL algorithms. * Make size() `constexpr`. * Rename string() to str() for consistency with internal C++ naming. * Add begin() and end(). * Add operator=() which accepts a UUID pointer. Signed-off-by: Philippe Proulx Change-Id: Id049953aecc51562e5939db546cb7d82bbaf88eb Reviewed-on: https://review.lttng.org/c/babeltrace/+/10822 Tested-by: jenkins --- src/cpp-common/Makefile.am | 3 +- src/cpp-common/uuid-view.cpp | 21 +++++ src/cpp-common/uuid-view.hpp | 66 ++++++++++++--- src/cpp-common/uuid.hpp | 154 +++++++++++++++++++++++++++++++++++ 4 files changed, 232 insertions(+), 12 deletions(-) create mode 100644 src/cpp-common/uuid-view.cpp create mode 100644 src/cpp-common/uuid.hpp diff --git a/src/cpp-common/Makefile.am b/src/cpp-common/Makefile.am index 607b85ab..cfe4efd1 100644 --- a/src/cpp-common/Makefile.am +++ b/src/cpp-common/Makefile.am @@ -15,4 +15,5 @@ EXTRA_DIST = bt2 \ endian.hpp \ make-unique.hpp \ safe-ops.hpp \ - align.hpp + align.hpp \ + uuid.hpp diff --git a/src/cpp-common/uuid-view.cpp b/src/cpp-common/uuid-view.cpp new file mode 100644 index 00000000..7257277f --- /dev/null +++ b/src/cpp-common/uuid-view.cpp @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016-2022 Philippe Proulx + * + * SPDX-License-Identifier: MIT + */ + +#include "uuid.hpp" +#include "uuid-view.hpp" + +namespace bt2_common { + +UuidView::UuidView(const Uuid& uuid) noexcept : _mUuid {uuid.data()} +{ +} + +UuidView::operator Uuid() const noexcept +{ + return Uuid {*this}; +} + +} /* namespace bt2_common */ diff --git a/src/cpp-common/uuid-view.hpp b/src/cpp-common/uuid-view.hpp index 8829019b..c45c8ac3 100644 --- a/src/cpp-common/uuid-view.hpp +++ b/src/cpp-common/uuid-view.hpp @@ -10,23 +10,55 @@ #include #include #include +#include #include "common/assert.h" #include "common/uuid.h" namespace bt2_common { +class Uuid; + +/* + * A view on existing UUID data. + * + * A `UuidView` object doesn't contain its UUID data: see `Uuid` for a + * UUID data container. + */ class UuidView final { public: - explicit UuidView(const std::uint8_t * const uuid) noexcept : _mUuid {uuid} + using Val = std::uint8_t; + using ConstIter = const Val *; + +public: + explicit UuidView(const Val * const uuid) noexcept : _mUuid {uuid} { BT_ASSERT_DBG(uuid); } + explicit UuidView(const Uuid& uuid) noexcept; UuidView(const UuidView&) noexcept = default; UuidView& operator=(const UuidView&) noexcept = default; + UuidView& operator=(const Val * const uuid) noexcept + { + _mUuid = uuid; + return *this; + } + + operator Uuid() const noexcept; + + std::string str() const + { + std::string s; + + s.resize(BT_UUID_STR_LEN); + bt_uuid_to_str(_mUuid, &s[0]); + + return s; + } + bool operator==(const UuidView& other) const noexcept { return bt_uuid_compare(_mUuid, other._mUuid) == 0; @@ -42,28 +74,40 @@ public: return bt_uuid_compare(_mUuid, other._mUuid) < 0; } - std::string str() const + static constexpr std::size_t size() noexcept { - std::string s; - - s.resize(BT_UUID_STR_LEN); - bt_uuid_to_str(_mUuid, &s[0]); + return BT_UUID_LEN; + } - return s; + const Val *data() const noexcept + { + return _mUuid; } - static constexpr std::size_t size() noexcept + Val operator[](const std::size_t index) const noexcept { - return BT_UUID_LEN; + return _mUuid[index]; } - const std::uint8_t *data() const noexcept + ConstIter begin() const noexcept { return _mUuid; } + ConstIter end() const noexcept + { + return _mUuid + this->size(); + } + + bool isNil() const noexcept + { + return std::all_of(this->begin(), this->end(), [](const std::uint8_t byte) { + return byte == 0; + }); + } + private: - const std::uint8_t *_mUuid; + const Val *_mUuid; }; } /* namespace bt2_common */ diff --git a/src/cpp-common/uuid.hpp b/src/cpp-common/uuid.hpp new file mode 100644 index 00000000..935091fc --- /dev/null +++ b/src/cpp-common/uuid.hpp @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2022 Francis Deslauriers + * + * SPDX-License-Identifier: MIT + */ + +#ifndef BABELTRACE_CPP_COMMON_UUID_HPP +#define BABELTRACE_CPP_COMMON_UUID_HPP + +#include +#include +#include +#include + +#include "common/assert.h" +#include "common/uuid.h" +#include "uuid-view.hpp" + +namespace bt2_common { + +/* + * A universally unique identifier. + * + * A `Uuid` object contains its UUID data: see `UuidView` to have a + * UUID view on existing UUID data. + */ +class Uuid final +{ +public: + using Val = UuidView::Val; + using ConstIter = UuidView::ConstIter; + +public: + /* + * Builds a nil UUID. + */ + explicit Uuid() noexcept = default; + + explicit Uuid(const Val * const uuid) noexcept + { + this->_setFromPtr(uuid); + } + + explicit Uuid(const char * const str) noexcept + { + const auto ret = bt_uuid_from_str(str, _mUuid.data()); + BT_ASSERT(ret == 0); + } + + explicit Uuid(const std::string& str) noexcept : Uuid {str.c_str()} + { + } + + explicit Uuid(const UuidView& view) noexcept : Uuid {view.data()} + { + } + + Uuid(const Uuid&) noexcept = default; + Uuid& operator=(const Uuid&) noexcept = default; + + Uuid& operator=(const Val * const uuid) noexcept + { + this->_setFromPtr(uuid); + return *this; + } + + static Uuid generate() noexcept + { + bt_uuid_t uuidGen; + + bt_uuid_generate(uuidGen); + return Uuid {uuidGen}; + } + + std::string str() const + { + return this->_view().str(); + } + + bool operator==(const Uuid& other) const noexcept + { + return this->_view() == other._view(); + } + + bool operator!=(const Uuid& other) const noexcept + { + return this->_view() != other._view(); + } + + bool operator<(const Uuid& other) const noexcept + { + return this->_view() < other._view(); + } + + /* + * The returned UUID view must not outlive the UUID object. + */ + operator UuidView() const noexcept + { + return this->_view(); + } + + static constexpr std::size_t size() noexcept + { + return UuidView::size(); + } + + const Val *data() const noexcept + { + return _mUuid.data(); + } + + Val operator[](const std::size_t index) const noexcept + { + return this->_view()[index]; + } + + ConstIter begin() const noexcept + { + return this->_view().begin(); + } + + ConstIter end() const noexcept + { + return this->_view().end(); + } + + bool isNil() const noexcept + { + return this->_view().isNil(); + } + +private: + /* + * std::copy_n() won't throw when simply copying bytes below, + * therefore this method won't throw. + */ + void _setFromPtr(const Val * const uuid) noexcept + { + BT_ASSERT(uuid); + std::copy_n(uuid, BT_UUID_LEN, std::begin(_mUuid)); + } + + UuidView _view() const noexcept + { + return UuidView {_mUuid.data()}; + } + + std::array _mUuid = {}; +}; + +} /* namespace bt2_common */ + +#endif /* BABELTRACE_CPP_COMMON_UUID_HPP */ -- 2.34.1