blob: a253da1f3954eed84541177cfee46df4c17a7dfa [file] [log] [blame]
Luis Hector Chavez21a249e2017-07-26 17:38:05 +00001// Copyright 2013 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_ARRAY_H_
6#define MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_
7
8#include <stddef.h>
9#include <string.h>
10#include <algorithm>
11#include <set>
12#include <string>
13#include <utility>
14#include <vector>
15
16#include "base/macros.h"
17#include "mojo/public/cpp/bindings/lib/array_internal.h"
18#include "mojo/public/cpp/bindings/lib/bindings_internal.h"
19#include "mojo/public/cpp/bindings/lib/clone_equals_util.h"
20#include "mojo/public/cpp/bindings/lib/template_util.h"
21#include "mojo/public/cpp/bindings/type_converter.h"
22
23namespace mojo {
24
25// Represents a moveable array with contents of type |T|. The array can be null,
26// meaning that no value has been assigned to it. Null is distinct from empty.
27template <typename T>
28class Array {
29 public:
30 using ConstRefType = typename std::vector<T>::const_reference;
31 using RefType = typename std::vector<T>::reference;
32
33 using Element = T;
34
35 using iterator = typename std::vector<T>::iterator;
36 using const_iterator = typename std::vector<T>::const_iterator;
37
38 // Constructs an empty array.
39 Array() : is_null_(false) {}
40 // Constructs a null array.
41 Array(std::nullptr_t null_pointer) : is_null_(true) {}
42
43 // Constructs a new non-null array of the specified size. The elements will
44 // be value-initialized (meaning that they will be initialized by their
45 // default constructor, if any, or else zero-initialized).
46 explicit Array(size_t size) : vec_(size), is_null_(false) {}
47 ~Array() {}
48
49 // Copies the contents of |other| into this array.
50 Array(const std::vector<T>& other) : vec_(other), is_null_(false) {}
51
52 // Moves the contents of |other| into this array.
53 Array(std::vector<T>&& other) : vec_(std::move(other)), is_null_(false) {}
54 Array(Array&& other) : is_null_(true) { Take(&other); }
55
56 Array& operator=(std::vector<T>&& other) {
57 vec_ = std::move(other);
58 is_null_ = false;
59 return *this;
60 }
61 Array& operator=(Array&& other) {
62 Take(&other);
63 return *this;
64 }
65
66 Array& operator=(std::nullptr_t null_pointer) {
67 is_null_ = true;
68 vec_.clear();
69 return *this;
70 }
71
72 // Creates a non-null array of the specified size. The elements will be
73 // value-initialized (meaning that they will be initialized by their default
74 // constructor, if any, or else zero-initialized).
75 static Array New(size_t size) { return Array(size); }
76
77 // Creates a new array with a copy of the contents of |other|.
78 template <typename U>
79 static Array From(const U& other) {
80 return TypeConverter<Array, U>::Convert(other);
81 }
82
83 // Copies the contents of this array to a new object of type |U|.
84 template <typename U>
85 U To() const {
86 return TypeConverter<U, Array>::Convert(*this);
87 }
88
89 // Indicates whether the array is null (which is distinct from empty).
90 bool is_null() const { return is_null_; }
91
92 // Indicates whether the array is empty (which is distinct from null).
93 bool empty() const { return vec_.empty() && !is_null_; }
94
95 // Returns a reference to the first element of the array. Calling this on a
96 // null or empty array causes undefined behavior.
97 ConstRefType front() const { return vec_.front(); }
98 RefType front() { return vec_.front(); }
99
100 iterator begin() { return vec_.begin(); }
101 const_iterator begin() const { return vec_.begin(); }
102 iterator end() { return vec_.end(); }
103 const_iterator end() const { return vec_.end(); }
104
105 // Returns the size of the array, which will be zero if the array is null.
106 size_t size() const { return vec_.size(); }
107
108 // Returns a reference to the element at zero-based |offset|. Calling this on
109 // an array with size less than |offset|+1 causes undefined behavior.
110 ConstRefType at(size_t offset) const { return vec_.at(offset); }
111 ConstRefType operator[](size_t offset) const { return at(offset); }
112 RefType at(size_t offset) { return vec_.at(offset); }
113 RefType operator[](size_t offset) { return at(offset); }
114
115 // Pushes |value| onto the back of the array. If this array was null, it will
116 // become non-null with a size of 1.
117 void push_back(const T& value) {
118 is_null_ = false;
119 vec_.push_back(value);
120 }
121 void push_back(T&& value) {
122 is_null_ = false;
123 vec_.push_back(std::move(value));
124 }
125
126 // Resizes the array to |size| and makes it non-null. Otherwise, works just
127 // like the resize method of |std::vector|.
128 void resize(size_t size) {
129 is_null_ = false;
130 vec_.resize(size);
131 }
132
133 // Sets the array to empty (even if previously it was null.)
134 void SetToEmpty() { resize(0); }
135
136 // Returns a const reference to the |std::vector| managed by this class. If
137 // the array is null, this will be an empty vector.
138 const std::vector<T>& storage() const { return vec_; }
139
140 // Passes the underlying storage and resets this array to null.
141 std::vector<T> PassStorage() {
142 is_null_ = true;
143 return std::move(vec_);
144 }
145
146 operator const std::vector<T>&() const { return vec_; }
147
148 void Swap(Array* other) {
149 std::swap(is_null_, other->is_null_);
150 vec_.swap(other->vec_);
151 }
152
153 // Swaps the contents of this array with the specified vector, making this
154 // array non-null. Since the vector cannot represent null, it will just be
155 // made empty if this array is null.
156 void Swap(std::vector<T>* other) {
157 is_null_ = false;
158 vec_.swap(*other);
159 }
160
161 // Returns a copy of the array where each value of the new array has been
162 // "cloned" from the corresponding value of this array. If the element type
163 // defines a Clone() method, it will be used; otherwise copy
164 // constructor/assignment will be used.
165 //
166 // Please note that calling this method will fail compilation if the element
167 // type cannot be cloned (which usually means that it is a Mojo handle type or
168 // a type containing Mojo handles).
169 Array Clone() const {
170 Array result;
171 result.is_null_ = is_null_;
172 result.vec_ = internal::Clone(vec_);
173 return result;
174 }
175
176 // Indicates whether the contents of this array are equal to |other|. A null
177 // array is only equal to another null array. If the element type defines an
178 // Equals() method, it will be used; otherwise == operator will be used.
179 bool Equals(const Array& other) const {
180 if (is_null() != other.is_null())
181 return false;
182 return internal::Equals(vec_, other.vec_);
183 }
184
185 private:
186 typedef std::vector<T> Array::*Testable;
187
188 public:
189 operator Testable() const { return is_null_ ? 0 : &Array::vec_; }
190
191 private:
192 // Forbid the == and != operators explicitly, otherwise Array will be
193 // converted to Testable to do == or != comparison.
194 template <typename U>
195 bool operator==(const Array<U>& other) const = delete;
196 template <typename U>
197 bool operator!=(const Array<U>& other) const = delete;
198
199 void Take(Array* other) {
200 operator=(nullptr);
201 Swap(other);
202 }
203
204 std::vector<T> vec_;
205 bool is_null_;
206
207 DISALLOW_COPY_AND_ASSIGN(Array);
208};
209
210// A |TypeConverter| that will create an |Array<T>| containing a copy of the
211// contents of an |std::vector<E>|, using |TypeConverter<T, E>| to copy each
212// element. The returned array will always be non-null.
213template <typename T, typename E>
214struct TypeConverter<Array<T>, std::vector<E>> {
215 static Array<T> Convert(const std::vector<E>& input) {
216 Array<T> result(input.size());
217 for (size_t i = 0; i < input.size(); ++i)
218 result[i] = TypeConverter<T, E>::Convert(input[i]);
219 return std::move(result);
220 }
221};
222
223// A |TypeConverter| that will create an |std::vector<E>| containing a copy of
224// the contents of an |Array<T>|, using |TypeConverter<E, T>| to copy each
225// element. If the input array is null, the output vector will be empty.
226template <typename E, typename T>
227struct TypeConverter<std::vector<E>, Array<T>> {
228 static std::vector<E> Convert(const Array<T>& input) {
229 std::vector<E> result;
230 if (!input.is_null()) {
231 result.resize(input.size());
232 for (size_t i = 0; i < input.size(); ++i)
233 result[i] = TypeConverter<E, T>::Convert(input[i]);
234 }
235 return result;
236 }
237};
238
239// A |TypeConverter| that will create an |Array<T>| containing a copy of the
240// contents of an |std::set<E>|, using |TypeConverter<T, E>| to copy each
241// element. The returned array will always be non-null.
242template <typename T, typename E>
243struct TypeConverter<Array<T>, std::set<E>> {
244 static Array<T> Convert(const std::set<E>& input) {
245 Array<T> result;
246 for (auto i : input)
247 result.push_back(TypeConverter<T, E>::Convert(i));
248 return std::move(result);
249 }
250};
251
252// A |TypeConverter| that will create an |std::set<E>| containing a copy of
253// the contents of an |Array<T>|, using |TypeConverter<E, T>| to copy each
254// element. If the input array is null, the output set will be empty.
255template <typename E, typename T>
256struct TypeConverter<std::set<E>, Array<T>> {
257 static std::set<E> Convert(const Array<T>& input) {
258 std::set<E> result;
259 if (!input.is_null()) {
260 for (size_t i = 0; i < input.size(); ++i)
261 result.insert(TypeConverter<E, T>::Convert(input[i]));
262 }
263 return result;
264 }
265};
266
267// Less than operator to allow Arrays as keys in std maps and sets.
268template <typename T>
269inline bool operator<(const Array<T>& a, const Array<T>& b) {
270 if (a.is_null())
271 return !b.is_null();
272 if (b.is_null())
273 return false;
274 return a.storage() < b.storage();
275}
276
277} // namespace mojo
278
279#endif // MOJO_PUBLIC_CPP_BINDINGS_ARRAY_H_