blob: c8ed069d55570b1f6bf5e7191bcf121626dd0a0b [file] [log] [blame]
Karl Wibergbe579832015-11-10 22:34:18 +01001/*
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10
11#ifndef WEBRTC_BASE_OPTIONAL_H_
12#define WEBRTC_BASE_OPTIONAL_H_
13
14#include <algorithm>
kwibergbfefb032016-05-01 14:53:46 -070015#include <memory>
Karl Wibergbe579832015-11-10 22:34:18 +010016#include <utility>
17
ossue5c27a52017-02-20 04:41:42 -080018#ifdef UNIT_TEST
19#include <iomanip>
20#include <ostream>
21#endif // UNIT_TEST
22
kwiberg2b11fd22016-09-09 03:35:24 -070023#include "webrtc/base/array_view.h"
Karl Wibergbe579832015-11-10 22:34:18 +010024#include "webrtc/base/checks.h"
kwiberg2b11fd22016-09-09 03:35:24 -070025#include "webrtc/base/sanitizer.h"
Karl Wibergbe579832015-11-10 22:34:18 +010026
27namespace rtc {
28
kwiberg2b11fd22016-09-09 03:35:24 -070029namespace optional_internal {
30
31#if RTC_HAS_ASAN
32
ossue5c27a52017-02-20 04:41:42 -080033// This is a non-inlined function. The optimizer can't see inside it. It
34// prevents the compiler from generating optimized code that reads value_ even
35// if it is unset. Although safe, this causes memory sanitizers to complain.
kwiberg2b11fd22016-09-09 03:35:24 -070036void* FunctionThatDoesNothingImpl(void*);
37
38template <typename T>
39inline T* FunctionThatDoesNothing(T* x) {
40 return reinterpret_cast<T*>(
41 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x)));
42}
43
44#else
45
46template <typename T>
47inline T* FunctionThatDoesNothing(T* x) { return x; }
48
49#endif
50
51} // namespace optional_internal
52
kwibergd0404802016-05-09 06:06:05 -070053// Simple std::optional-wannabe. It either contains a T or not.
Karl Wibergbe579832015-11-10 22:34:18 +010054//
55// A moved-from Optional<T> may only be destroyed, and assigned to if T allows
56// being assigned to after having been moved from. Specifically, you may not
57// assume that it just doesn't contain a value anymore.
58//
59// Examples of good places to use Optional:
60//
61// - As a class or struct member, when the member doesn't always have a value:
62// struct Prisoner {
63// std::string name;
64// Optional<int> cell_number; // Empty if not currently incarcerated.
65// };
66//
67// - As a return value for functions that may fail to return a value on all
68// allowed inputs. For example, a function that searches an array might
69// return an Optional<size_t> (the index where it found the element, or
70// nothing if it didn't find it); and a function that parses numbers might
71// return Optional<double> (the parsed number, or nothing if parsing failed).
72//
73// Examples of bad places to use Optional:
74//
75// - As a return value for functions that may fail because of disallowed
76// inputs. For example, a string length function should not return
77// Optional<size_t> so that it can return nothing in case the caller passed
78// it a null pointer; the function should probably use RTC_[D]CHECK instead,
79// and return plain size_t.
80//
81// - As a return value for functions that may fail to return a value on all
82// allowed inputs, but need to tell the caller what went wrong. Returning
83// Optional<double> when parsing a single number as in the example above
84// might make sense, but any larger parse job is probably going to need to
85// tell the caller what the problem was, not just that there was one.
86//
kwibergb3f7dbc2017-01-10 02:11:17 -080087// - As a non-mutable function argument. When you want to pass a value of a
88// type T that can fail to be there, const T* is almost always both fastest
89// and cleanest. (If you're *sure* that the the caller will always already
90// have an Optional<T>, const Optional<T>& is slightly faster than const T*,
91// but this is a micro-optimization. In general, stick to const T*.)
92//
Karl Wibergbe579832015-11-10 22:34:18 +010093// TODO(kwiberg): Get rid of this class when the standard library has
94// std::optional (and we're allowed to use it).
95template <typename T>
96class Optional final {
97 public:
98 // Construct an empty Optional.
kwiberg2b11fd22016-09-09 03:35:24 -070099 Optional() : has_value_(false), empty_('\0') {
100 PoisonValue();
101 }
Karl Wibergbe579832015-11-10 22:34:18 +0100102
103 // Construct an Optional that contains a value.
kwibergd0404802016-05-09 06:06:05 -0700104 explicit Optional(const T& value) : has_value_(true) {
105 new (&value_) T(value);
106 }
107 explicit Optional(T&& value) : has_value_(true) {
108 new (&value_) T(std::move(value));
109 }
Karl Wibergbe579832015-11-10 22:34:18 +0100110
kwibergd0404802016-05-09 06:06:05 -0700111 // Copy constructor: copies the value from m if it has one.
112 Optional(const Optional& m) : has_value_(m.has_value_) {
113 if (has_value_)
114 new (&value_) T(m.value_);
kwiberg2b11fd22016-09-09 03:35:24 -0700115 else
116 PoisonValue();
kwibergd0404802016-05-09 06:06:05 -0700117 }
Karl Wibergbe579832015-11-10 22:34:18 +0100118
kwibergd0404802016-05-09 06:06:05 -0700119 // Move constructor: if m has a value, moves the value from m, leaving m
120 // still in a state where it has a value, but a moved-from one (the
121 // properties of which depends on T; the only general guarantee is that we
122 // can destroy m).
123 Optional(Optional&& m) : has_value_(m.has_value_) {
124 if (has_value_)
125 new (&value_) T(std::move(m.value_));
kwiberg2b11fd22016-09-09 03:35:24 -0700126 else
127 PoisonValue();
kwibergd0404802016-05-09 06:06:05 -0700128 }
Karl Wibergbe579832015-11-10 22:34:18 +0100129
kwibergd0404802016-05-09 06:06:05 -0700130 ~Optional() {
131 if (has_value_)
132 value_.~T();
kwiberg2b11fd22016-09-09 03:35:24 -0700133 else
134 UnpoisonValue();
kwibergd0404802016-05-09 06:06:05 -0700135 }
136
137 // Copy assignment. Uses T's copy assignment if both sides have a value, T's
138 // copy constructor if only the right-hand side has a value.
139 Optional& operator=(const Optional& m) {
140 if (m.has_value_) {
141 if (has_value_) {
142 value_ = m.value_; // T's copy assignment.
143 } else {
kwiberg2b11fd22016-09-09 03:35:24 -0700144 UnpoisonValue();
kwibergd0404802016-05-09 06:06:05 -0700145 new (&value_) T(m.value_); // T's copy constructor.
146 has_value_ = true;
147 }
danilchapc4fd23c2016-10-17 07:16:54 -0700148 } else {
149 reset();
kwibergd0404802016-05-09 06:06:05 -0700150 }
151 return *this;
152 }
153
154 // Move assignment. Uses T's move assignment if both sides have a value, T's
155 // move constructor if only the right-hand side has a value. The state of m
156 // after it's been moved from is as for the move constructor.
157 Optional& operator=(Optional&& m) {
158 if (m.has_value_) {
159 if (has_value_) {
160 value_ = std::move(m.value_); // T's move assignment.
161 } else {
kwiberg2b11fd22016-09-09 03:35:24 -0700162 UnpoisonValue();
kwibergd0404802016-05-09 06:06:05 -0700163 new (&value_) T(std::move(m.value_)); // T's move constructor.
164 has_value_ = true;
165 }
danilchapc4fd23c2016-10-17 07:16:54 -0700166 } else {
167 reset();
kwibergd0404802016-05-09 06:06:05 -0700168 }
169 return *this;
170 }
171
172 // Swap the values if both m1 and m2 have values; move the value if only one
173 // of them has one.
Karl Wibergbe579832015-11-10 22:34:18 +0100174 friend void swap(Optional& m1, Optional& m2) {
kwibergd0404802016-05-09 06:06:05 -0700175 if (m1.has_value_) {
176 if (m2.has_value_) {
177 // Both have values: swap.
178 using std::swap;
179 swap(m1.value_, m2.value_);
180 } else {
181 // Only m1 has a value: move it to m2.
kwiberg2b11fd22016-09-09 03:35:24 -0700182 m2.UnpoisonValue();
kwibergd0404802016-05-09 06:06:05 -0700183 new (&m2.value_) T(std::move(m1.value_));
184 m1.value_.~T(); // Destroy the moved-from value.
185 m1.has_value_ = false;
186 m2.has_value_ = true;
kwiberg2b11fd22016-09-09 03:35:24 -0700187 m1.PoisonValue();
kwibergd0404802016-05-09 06:06:05 -0700188 }
189 } else if (m2.has_value_) {
190 // Only m2 has a value: move it to m1.
kwiberg2b11fd22016-09-09 03:35:24 -0700191 m1.UnpoisonValue();
kwibergd0404802016-05-09 06:06:05 -0700192 new (&m1.value_) T(std::move(m2.value_));
193 m2.value_.~T(); // Destroy the moved-from value.
194 m1.has_value_ = true;
195 m2.has_value_ = false;
kwiberg2b11fd22016-09-09 03:35:24 -0700196 m2.PoisonValue();
kwibergd0404802016-05-09 06:06:05 -0700197 }
Karl Wibergbe579832015-11-10 22:34:18 +0100198 }
199
danilchapc4fd23c2016-10-17 07:16:54 -0700200 // Destroy any contained value. Has no effect if we have no value.
201 void reset() {
202 if (!has_value_)
203 return;
204 value_.~T();
205 has_value_ = false;
206 PoisonValue();
207 }
208
danilchap9e83c972016-10-18 04:07:18 -0700209 template <class... Args>
210 void emplace(Args&&... args) {
211 if (has_value_)
212 value_.~T();
213 else
214 UnpoisonValue();
215 new (&value_) T(std::forward<Args>(args)...);
216 has_value_ = true;
217 }
218
Karl Wibergbe579832015-11-10 22:34:18 +0100219 // Conversion to bool to test if we have a value.
220 explicit operator bool() const { return has_value_; }
221
222 // Dereferencing. Only allowed if we have a value.
223 const T* operator->() const {
224 RTC_DCHECK(has_value_);
225 return &value_;
226 }
227 T* operator->() {
228 RTC_DCHECK(has_value_);
229 return &value_;
230 }
231 const T& operator*() const {
232 RTC_DCHECK(has_value_);
233 return value_;
234 }
235 T& operator*() {
236 RTC_DCHECK(has_value_);
237 return value_;
238 }
239
240 // Dereference with a default value in case we don't have a value.
241 const T& value_or(const T& default_val) const {
kwiberg2b11fd22016-09-09 03:35:24 -0700242 // The no-op call prevents the compiler from generating optimized code that
243 // reads value_ even if !has_value_, but only if FunctionThatDoesNothing is
244 // not completely inlined; see its declaration.).
245 return has_value_ ? *optional_internal::FunctionThatDoesNothing(&value_)
246 : default_val;
Karl Wibergbe579832015-11-10 22:34:18 +0100247 }
248
deadbeef81baed32017-02-10 18:11:11 -0800249 // Dereference and move value.
250 T MoveValue() {
251 RTC_DCHECK(has_value_);
252 return std::move(value_);
253 }
254
Karl Wibergbe579832015-11-10 22:34:18 +0100255 // Equality tests. Two Optionals are equal if they contain equivalent values,
danilchape0370602016-10-20 00:58:15 -0700256 // or if they're both empty.
Karl Wibergbe579832015-11-10 22:34:18 +0100257 friend bool operator==(const Optional& m1, const Optional& m2) {
258 return m1.has_value_ && m2.has_value_ ? m1.value_ == m2.value_
259 : m1.has_value_ == m2.has_value_;
260 }
danilchape0370602016-10-20 00:58:15 -0700261 friend bool operator==(const Optional& opt, const T& value) {
262 return opt.has_value_ && opt.value_ == value;
263 }
264 friend bool operator==(const T& value, const Optional& opt) {
265 return opt.has_value_ && value == opt.value_;
266 }
267
Karl Wibergbe579832015-11-10 22:34:18 +0100268 friend bool operator!=(const Optional& m1, const Optional& m2) {
269 return m1.has_value_ && m2.has_value_ ? m1.value_ != m2.value_
270 : m1.has_value_ != m2.has_value_;
271 }
danilchape0370602016-10-20 00:58:15 -0700272 friend bool operator!=(const Optional& opt, const T& value) {
273 return !opt.has_value_ || opt.value_ != value;
274 }
275 friend bool operator!=(const T& value, const Optional& opt) {
276 return !opt.has_value_ || value != opt.value_;
277 }
Karl Wibergbe579832015-11-10 22:34:18 +0100278
279 private:
kwiberg2b11fd22016-09-09 03:35:24 -0700280 // Tell sanitizers that value_ shouldn't be touched.
281 void PoisonValue() {
282 rtc::AsanPoison(rtc::MakeArrayView(&value_, 1));
283 rtc::MsanMarkUninitialized(rtc::MakeArrayView(&value_, 1));
284 }
285
286 // Tell sanitizers that value_ is OK to touch again.
287 void UnpoisonValue() {
288 rtc::AsanUnpoison(rtc::MakeArrayView(&value_, 1));
289 }
290
kwibergd0404802016-05-09 06:06:05 -0700291 bool has_value_; // True iff value_ contains a live value.
292 union {
ossuea416942016-06-30 02:14:54 -0700293 // empty_ exists only to make it possible to initialize the union, even when
294 // it doesn't contain any data. If the union goes uninitialized, it may
295 // trigger compiler warnings.
296 char empty_;
kwibergd0404802016-05-09 06:06:05 -0700297 // By placing value_ in a union, we get to manage its construction and
298 // destruction manually: the Optional constructors won't automatically
299 // construct it, and the Optional destructor won't automatically destroy
300 // it. Basically, this just allocates a properly sized and aligned block of
301 // memory in which we can manually put a T with placement new.
302 T value_;
303 };
Karl Wibergbe579832015-11-10 22:34:18 +0100304};
305
ossue5c27a52017-02-20 04:41:42 -0800306#ifdef UNIT_TEST
307namespace optional_internal {
308
309// Checks if there's a valid PrintTo(const T&, std::ostream*) call for T.
310template <typename T>
311struct HasPrintTo {
312 private:
313 struct No {};
314
315 template <typename T2>
316 static auto Test(const T2& obj)
317 -> decltype(PrintTo(obj, std::declval<std::ostream*>()));
318
319 template <typename>
320 static No Test(...);
321
322 public:
323 static constexpr bool value =
324 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
325};
326
327// Checks if there's a valid operator<<(std::ostream&, const T&) call for T.
328template <typename T>
329struct HasOstreamOperator {
330 private:
331 struct No {};
332
333 template <typename T2>
334 static auto Test(const T2& obj)
335 -> decltype(std::declval<std::ostream&>() << obj);
336
337 template <typename>
338 static No Test(...);
339
340 public:
341 static constexpr bool value =
342 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
343};
344
345// Prefer using PrintTo to print the object.
346template <typename T>
347typename std::enable_if<HasPrintTo<T>::value, void>::type OptionalPrintToHelper(
348 const T& value,
349 std::ostream* os) {
350 PrintTo(value, os);
351}
352
353// Fall back to operator<<(std::ostream&, ...) if it exists.
354template <typename T>
355typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
356 void>::type
357OptionalPrintToHelper(const T& value, std::ostream* os) {
358 *os << value;
359}
360
361inline void OptionalPrintObjectBytes(const unsigned char* bytes,
362 size_t size,
363 std::ostream* os) {
364 *os << "<optional with " << size << "-byte object [";
365 for (size_t i = 0; i != size; ++i) {
366 *os << (i == 0 ? "" : ((i & 1) ? "-" : " "));
367 *os << std::hex << std::setw(2) << std::setfill('0')
368 << static_cast<int>(bytes[i]);
369 }
370 *os << "]>";
371}
372
373// As a final back-up, just print the contents of the objcets byte-wise.
374template <typename T>
375typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
376 void>::type
377OptionalPrintToHelper(const T& value, std::ostream* os) {
378 OptionalPrintObjectBytes(reinterpret_cast<const unsigned char*>(&value),
379 sizeof(value), os);
380}
381
382} // namespace optional_internal
383
384// PrintTo is used by gtest to print out the results of tests. We want to ensure
385// the object contained in an Optional can be printed out if it's set, while
386// avoiding touching the object's storage if it is undefined.
387template <typename T>
388void PrintTo(const rtc::Optional<T>& opt, std::ostream* os) {
389 if (opt) {
390 optional_internal::OptionalPrintToHelper(*opt, os);
391 } else {
392 *os << "<empty optional>";
393 }
394}
395
396#endif // UNIT_TEST
397
Karl Wibergbe579832015-11-10 22:34:18 +0100398} // namespace rtc
399
400#endif // WEBRTC_BASE_OPTIONAL_H_