1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef MOJO_PUBLIC_CPP_BINDINGS_WTF_ARRAY_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_WTF_ARRAY_H_ 7 8 #include <stddef.h> 9 #include <utility> 10 11 #include "base/macros.h" 12 #include "mojo/public/cpp/bindings/lib/array_internal.h" 13 #include "mojo/public/cpp/bindings/lib/bindings_internal.h" 14 #include "mojo/public/cpp/bindings/lib/template_util.h" 15 #include "mojo/public/cpp/bindings/lib/wtf_clone_equals_util.h" 16 #include "mojo/public/cpp/bindings/type_converter.h" 17 #include "third_party/WebKit/Source/wtf/Vector.h" 18 19 namespace mojo { 20 21 // Represents an array backed by WTF::Vector. Comparing with WTF::Vector, 22 // mojo::WTFArray is move-only and can be null. 23 // It is easy to convert between WTF::Vector<T> and mojo::WTFArray<T>: 24 // - constructor WTFArray(WTF::Vector<T>&&) takes the contents of a 25 // WTF::Vector<T>; 26 // - method PassStorage() passes the underlying WTF::Vector. 27 template <typename T> 28 class WTFArray { 29 public: 30 // Constructs an empty array. WTFArray()31 WTFArray() : is_null_(false) {} 32 // Constructs a null array. WTFArray(std::nullptr_t null_pointer)33 WTFArray(std::nullptr_t null_pointer) : is_null_(true) {} 34 35 // Constructs a new non-null array of the specified size. The elements will 36 // be value-initialized (meaning that they will be initialized by their 37 // default constructor, if any, or else zero-initialized). WTFArray(size_t size)38 explicit WTFArray(size_t size) : vec_(size), is_null_(false) {} ~WTFArray()39 ~WTFArray() {} 40 41 // Moves the contents of |other| into this array. WTFArray(WTF::Vector<T> && other)42 WTFArray(WTF::Vector<T>&& other) : vec_(std::move(other)), is_null_(false) {} WTFArray(WTFArray && other)43 WTFArray(WTFArray&& other) : is_null_(true) { Take(&other); } 44 45 WTFArray& operator=(WTF::Vector<T>&& other) { 46 vec_ = std::move(other); 47 is_null_ = false; 48 return *this; 49 } 50 WTFArray& operator=(WTFArray&& other) { 51 Take(&other); 52 return *this; 53 } 54 55 WTFArray& operator=(std::nullptr_t null_pointer) { 56 is_null_ = true; 57 vec_.clear(); 58 return *this; 59 } 60 61 // Creates a non-null array of the specified size. The elements will be 62 // value-initialized (meaning that they will be initialized by their default 63 // constructor, if any, or else zero-initialized). New(size_t size)64 static WTFArray New(size_t size) { return WTFArray(size); } 65 66 // Creates a new array with a copy of the contents of |other|. 67 template <typename U> From(const U & other)68 static WTFArray From(const U& other) { 69 return TypeConverter<WTFArray, U>::Convert(other); 70 } 71 72 // Copies the contents of this array to a new object of type |U|. 73 template <typename U> To()74 U To() const { 75 return TypeConverter<U, WTFArray>::Convert(*this); 76 } 77 78 // Indicates whether the array is null (which is distinct from empty). is_null()79 bool is_null() const { 80 // When the array is set to null, the underlying storage |vec_| shouldn't 81 // contain any elements. 82 DCHECK(!is_null_ || vec_.isEmpty()); 83 return is_null_; 84 } 85 86 // Indicates whether the array is empty (which is distinct from null). empty()87 bool empty() const { return vec_.isEmpty() && !is_null_; } 88 89 // Returns a reference to the first element of the array. Calling this on a 90 // null or empty array causes undefined behavior. front()91 const T& front() const { return vec_.first(); } front()92 T& front() { return vec_.first(); } 93 94 // Returns the size of the array, which will be zero if the array is null. size()95 size_t size() const { return vec_.size(); } 96 97 // Returns a reference to the element at zero-based |offset|. Calling this on 98 // an array with size less than |offset|+1 causes undefined behavior. at(size_t offset)99 const T& at(size_t offset) const { return vec_.at(offset); } 100 const T& operator[](size_t offset) const { return at(offset); } at(size_t offset)101 T& at(size_t offset) { return vec_.at(offset); } 102 T& operator[](size_t offset) { return at(offset); } 103 104 // Resizes the array to |size| and makes it non-null. Otherwise, works just 105 // like the resize method of |WTF::Vector|. resize(size_t size)106 void resize(size_t size) { 107 is_null_ = false; 108 vec_.resize(size); 109 } 110 111 // Sets the array to empty (even if previously it was null.) SetToEmpty()112 void SetToEmpty() { resize(0); } 113 114 // Returns a const reference to the |WTF::Vector| managed by this class. If 115 // the array is null, this will be an empty vector. storage()116 const WTF::Vector<T>& storage() const { return vec_; } 117 118 // Passes the underlying storage and resets this array to null. 119 // 120 // TODO(yzshen): Consider changing this to a rvalue-ref-qualified conversion 121 // to WTF::Vector<T> after we move to MSVC 2015. PassStorage()122 WTF::Vector<T> PassStorage() { 123 is_null_ = true; 124 return std::move(vec_); 125 } 126 Swap(WTFArray * other)127 void Swap(WTFArray* other) { 128 std::swap(is_null_, other->is_null_); 129 vec_.swap(other->vec_); 130 } 131 132 // Swaps the contents of this array with the specified vector, making this 133 // array non-null. Since the vector cannot represent null, it will just be 134 // made empty if this array is null. Swap(WTF::Vector<T> * other)135 void Swap(WTF::Vector<T>* other) { 136 is_null_ = false; 137 vec_.swap(*other); 138 } 139 140 // Returns a copy of the array where each value of the new array has been 141 // "cloned" from the corresponding value of this array. If the element type 142 // defines a Clone() method, it will be used; otherwise copy 143 // constructor/assignment will be used. 144 // 145 // Please note that calling this method will fail compilation if the element 146 // type cannot be cloned (which usually means that it is a Mojo handle type or 147 // a type containing Mojo handles). Clone()148 WTFArray Clone() const { 149 WTFArray result; 150 result.is_null_ = is_null_; 151 result.vec_ = internal::Clone(vec_); 152 return result; 153 } 154 155 // Indicates whether the contents of this array are equal to |other|. A null 156 // array is only equal to another null array. If the element type defines an 157 // Equals() method, it will be used; otherwise == operator will be used. Equals(const WTFArray & other)158 bool Equals(const WTFArray& other) const { 159 if (is_null() != other.is_null()) 160 return false; 161 return internal::Equals(vec_, other.vec_); 162 } 163 164 private: 165 // TODO(dcheng): Use an explicit conversion operator. 166 typedef WTF::Vector<T> WTFArray::*Testable; 167 168 public: Testable()169 operator Testable() const { 170 // When the array is set to null, the underlying storage |vec_| shouldn't 171 // contain any elements. 172 DCHECK(!is_null_ || vec_.isEmpty()); 173 return is_null_ ? 0 : &WTFArray::vec_; 174 } 175 176 private: 177 // Forbid the == and != operators explicitly, otherwise WTFArray will be 178 // converted to Testable to do == or != comparison. 179 template <typename U> 180 bool operator==(const WTFArray<U>& other) const = delete; 181 template <typename U> 182 bool operator!=(const WTFArray<U>& other) const = delete; 183 Take(WTFArray * other)184 void Take(WTFArray* other) { 185 operator=(nullptr); 186 Swap(other); 187 } 188 189 WTF::Vector<T> vec_; 190 bool is_null_; 191 192 DISALLOW_COPY_AND_ASSIGN(WTFArray); 193 }; 194 195 } // namespace mojo 196 197 #endif // MOJO_PUBLIC_CPP_BINDINGS_WTF_ARRAY_H_ 198