| // Copyright 2018 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #ifndef LIB_FIDL_CPP_VECTOR_H_ |
| #define LIB_FIDL_CPP_VECTOR_H_ |
| |
| #include <lib/fidl/cpp/builder.h> |
| #include <lib/fidl/cpp/comparison.h> |
| #include <lib/fit/optional.h> |
| #include <zircon/assert.h> |
| |
| #include <utility> |
| #include <vector> |
| |
| #include "lib/fidl/cpp/traits.h" |
| #include "lib/fidl/cpp/transition.h" |
| |
| namespace fidl { |
| |
| #if defined(FIDL_USE_FIT_OPTIONAL) |
| |
| template <typename T> |
| class VectorPtr : public fit::optional<std::vector<T>> { |
| public: |
| constexpr VectorPtr() = default; |
| |
| constexpr VectorPtr(fit::nullopt_t) noexcept {} |
| FIDL_FIT_OPTIONAL_DEPRECATED("Use fit::nullopt instead of nullptr") |
| constexpr VectorPtr(std::nullptr_t) noexcept {} |
| |
| VectorPtr(const VectorPtr&) = default; |
| VectorPtr& operator=(const VectorPtr&) = default; |
| |
| VectorPtr(VectorPtr&&) noexcept = default; |
| VectorPtr& operator=(VectorPtr&&) noexcept = default; |
| |
| // Move construct and move assignment from the value type |
| constexpr VectorPtr(std::vector<T>&& value) : fit::optional<std::vector<T>>(std::move(value)) {} |
| constexpr VectorPtr& operator=(std::vector<T>&& value) { |
| fit::optional<std::vector<T>>::operator=(std::move(value)); |
| return *this; |
| } |
| |
| // Copy construct and copy assignment from the value type |
| constexpr VectorPtr(const std::vector<T>& value) : fit::optional<std::vector<T>>(value) {} |
| constexpr VectorPtr& operator=(const std::vector<T>& value) { |
| fit::optional<std::vector<T>>::operator=(value); |
| return *this; |
| } |
| |
| explicit VectorPtr(size_t size) : fit::optional<std::vector<T>>(size) {} |
| |
| // Override unchecked accessors with versions that check. |
| constexpr std::vector<T>* operator->() { |
| if (!fit::optional<std::vector<T>>::has_value()) { |
| __builtin_trap(); |
| } |
| return fit::optional<std::vector<T>>::operator->(); |
| } |
| constexpr const std::vector<T>* operator->() const { |
| if (!fit::optional<std::vector<T>>::has_value()) { |
| __builtin_trap(); |
| } |
| return fit::optional<std::vector<T>>::operator->(); |
| } |
| |
| FIDL_FIT_OPTIONAL_DEPRECATED("Assign an empty std::vector") |
| VectorPtr& emplace() { |
| *this = std::move(std::vector<T>()); |
| return *this; |
| } |
| |
| FIDL_FIT_OPTIONAL_DEPRECATED("Assign an std::vector") |
| VectorPtr& emplace(std::initializer_list<std::vector<T>>&& ilist) { |
| *this = (std::move(std::vector<T>(ilist))); |
| return *this; |
| } |
| |
| FIDL_FIT_OPTIONAL_DEPRECATED("Assign an std::vector") |
| VectorPtr& emplace(std::vector<T>&& value) { |
| *this = std::move(value); |
| return *this; |
| } |
| }; |
| |
| #else |
| |
| // A representation of a FIDL vector that owns the memory for the vector. |
| // |
| // A VectorPtr has three states: (1) null, (2) empty, (3) contains data. You |
| // can check for the null state using the |is_null| method. |
| template <typename T> |
| class VectorPtr { |
| public: |
| VectorPtr() : is_null_if_empty_(true) {} |
| ~VectorPtr() = default; |
| VectorPtr(std::nullptr_t) : is_null_if_empty_(true) {} |
| explicit VectorPtr(size_t size) : vec_(std::vector<T>(size)), is_null_if_empty_(false) {} |
| VectorPtr(std::vector<T>&& vec) : vec_(std::move(vec)), is_null_if_empty_(false) {} |
| |
| VectorPtr(VectorPtr&& other) = default; |
| VectorPtr& operator=(VectorPtr&& other) = default; |
| |
| // Copy construct and assignment from a const std::vector<T>& |
| VectorPtr(const std::vector<T>& other) : vec_(other), is_null_if_empty_(false) {} |
| VectorPtr& operator=(const std::vector<T>& other) { |
| vec_ = other; |
| is_null_if_empty_ = false; |
| return *this; |
| } |
| |
| // Creates a VectorPtr of the given size. |
| // |
| // Equivalent to using the |VectorPtr(size_t)| constructor. |
| FIDL_FIT_OPTIONAL_DEPRECATED("use constructor") |
| static VectorPtr New(size_t size) { return VectorPtr(size); } |
| |
| // Accesses the underlying std::vector object. |
| FIDL_FIT_OPTIONAL_DEPRECATED("use value_or") |
| const std::vector<T>& get() const { return vec_; } |
| |
| // Takes the std::vector from the VectorPtr. |
| // |
| // After this method returns, the VectorPtr is null. |
| FIDL_FIT_OPTIONAL_DEPRECATED("use std::move(vecptr).value();vecptr.reset();") |
| std::vector<T> take() { |
| is_null_if_empty_ = true; |
| return std::move(vec_); |
| } |
| |
| // Stores the given std::vector in this VectorPtr. |
| // |
| // After this method returns, the VectorPtr is non-null. |
| FIDL_FIT_OPTIONAL_DEPRECATED("use assignment or emplace()") |
| void reset(std::vector<T> vec) { |
| vec_ = std::move(vec); |
| is_null_if_empty_ = false; |
| } |
| |
| VectorPtr& emplace() { |
| vec_.clear(); |
| is_null_if_empty_ = false; |
| return *this; |
| } |
| |
| VectorPtr& emplace(std::vector<T>&& vec) { |
| vec_ = std::move(vec); |
| is_null_if_empty_ = false; |
| return *this; |
| } |
| |
| VectorPtr& emplace(std::initializer_list<T>&& ilist) { |
| vec_ = std::vector<T>(ilist); |
| is_null_if_empty_ = false; |
| return *this; |
| } |
| |
| VectorPtr& operator=(std::vector<T>&& vec) { |
| vec_ = std::move(vec); |
| is_null_if_empty_ = false; |
| return *this; |
| } |
| |
| void reset() { |
| vec_.clear(); |
| is_null_if_empty_ = true; |
| } |
| |
| // Resizes the underlying std::vector in this VectorPtr to the given size. |
| // |
| // After this method returns, the VectorPtr is non-null. |
| FIDL_FIT_OPTIONAL_DEPRECATED("initialize and use operator->") |
| void resize(size_t size) { |
| vec_.resize(size); |
| is_null_if_empty_ = false; |
| } |
| |
| // Pushes |value| onto the back of this VectorPtr. |
| // |
| // If this vector was null, it will become non-null with a size of 1. |
| FIDL_FIT_OPTIONAL_DEPRECATED("initialize and use operator->") |
| void push_back(const T& value) { |
| vec_.push_back(value); |
| is_null_if_empty_ = false; |
| } |
| |
| // Pushes |value| onto the back of this VectorPtr. |
| // |
| // If this vector was null, it will become non-null with a size of 1. |
| FIDL_FIT_OPTIONAL_DEPRECATED("initialize and use operator->") |
| void push_back(T&& value) { |
| vec_.push_back(std::forward<T>(value)); |
| is_null_if_empty_ = false; |
| } |
| |
| void swap(VectorPtr& other) { |
| using std::swap; |
| swap(vec_, other.vec_); |
| swap(is_null_if_empty_, other.is_null_if_empty_); |
| } |
| |
| // Returns a copy of this VectorPtr. |
| // |
| // Unlike fidl::Clone, this function can never fail. However, this function |
| // works only if T is copiable. |
| FIDL_FIT_OPTIONAL_DEPRECATED("use fidl::Clone()") |
| VectorPtr Clone() const { |
| if (is_null()) |
| return VectorPtr(); |
| return VectorPtr(vec_); |
| } |
| |
| // Whether this VectorPtr is null. |
| // |
| // The null state is separate from the empty state. |
| FIDL_FIT_OPTIONAL_DEPRECATED("use !has_value()") |
| bool is_null() const { return is_null_if_empty_ && vec_.empty(); } |
| |
| bool has_value() const { return !is_null_if_empty_ || !vec_.empty(); } |
| |
| // Tests as true if non-null, false if null. |
| explicit operator bool() const { return has_value(); } |
| |
| // Provides access to the underlying std::vector. |
| std::vector<T>* operator->() { return &vec_; } |
| const std::vector<T>* operator->() const { return &vec_; } |
| |
| // Provides access to the underlying std::vector. |
| std::vector<T>& operator*() { return vec_; } |
| const std::vector<T>& operator*() const { return vec_; } |
| |
| std::vector<T>& value() & { return vec_; } |
| const std::vector<T>& value() const& { return vec_; } |
| |
| std::vector<T>& value_or(std::vector<T>& default_value) & { |
| return has_value() ? vec_ : default_value; |
| } |
| const std::vector<T>& value_or(const std::vector<T>& default_value) const& { |
| return has_value() ? vec_ : default_value; |
| } |
| |
| // Provides implicit conversion for accessing the underlying std::vector. |
| // To mutate the vector, use operator* or operator-> or one of the mutation |
| // functions. |
| FIDL_FIT_OPTIONAL_DEPRECATED("use value_or()") |
| operator const std::vector<T> &() const { return vec_; } |
| |
| private: |
| std::vector<T> vec_; |
| bool is_null_if_empty_; |
| }; |
| |
| #endif |
| |
| template <class T> |
| struct Equality<VectorPtr<T>> { |
| bool operator()(const VectorPtr<T>& lhs, const VectorPtr<T>& rhs) const { |
| if (!lhs.has_value() || !rhs.has_value()) { |
| return !lhs.has_value() == !rhs.has_value(); |
| } |
| return ::fidl::Equality<std::vector<T>>{}(lhs.value(), rhs.value()); |
| } |
| }; |
| |
| } // namespace fidl |
| |
| #endif // LIB_FIDL_CPP_VECTOR_H_ |