1 /*
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 API_OPTIONAL_H_
12 #define API_OPTIONAL_H_
13 
14 #include <algorithm>
15 #include <memory>
16 #include <utility>
17 
18 #ifdef UNIT_TEST
19 #include <iomanip>
20 #include <ostream>
21 #endif  // UNIT_TEST
22 
23 #include "api/array_view.h"
24 #include "rtc_base/checks.h"
25 #include "rtc_base/sanitizer.h"
26 
27 namespace rtc {
28 
29 namespace optional_internal {
30 
31 #if RTC_HAS_ASAN
32 
33 // 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.
36 const void* FunctionThatDoesNothingImpl(const void*);
37 
38 template <typename T>
FunctionThatDoesNothing(const T * x)39 inline const T* FunctionThatDoesNothing(const T* x) {
40   return reinterpret_cast<const T*>(
41       FunctionThatDoesNothingImpl(reinterpret_cast<const void*>(x)));
42 }
43 
44 
45 #else
46 
47 template <typename T>
48 inline T* FunctionThatDoesNothing(T* x) {
49   return x;
50 }
51 
52 #endif
53 
54 struct NulloptArg;
55 
56 }  // namespace optional_internal
57 
58 // nullopt_t must be a non-aggregate literal type with a constexpr constructor
59 // that takes some implementation-defined literal type. It mustn't have a
60 // default constructor nor an initializer-list constructor.
61 // See:
62 // http://en.cppreference.com/w/cpp/utility/optional/nullopt_t
63 // That page uses int, though this seems to confuse older versions of GCC.
64 struct nullopt_t {
nullopt_tnullopt_t65   constexpr explicit nullopt_t(rtc::optional_internal::NulloptArg&) {}
66 };
67 
68 // Specification:
69 // http://en.cppreference.com/w/cpp/utility/optional/nullopt
70 extern const nullopt_t nullopt;
71 
72 // Simple std::optional-wannabe. It either contains a T or not.
73 //
74 // A moved-from Optional<T> may only be destroyed, and assigned to if T allows
75 // being assigned to after having been moved from. Specifically, you may not
76 // assume that it just doesn't contain a value anymore.
77 //
78 // Examples of good places to use Optional:
79 //
80 // - As a class or struct member, when the member doesn't always have a value:
81 //     struct Prisoner {
82 //       std::string name;
83 //       Optional<int> cell_number;  // Empty if not currently incarcerated.
84 //     };
85 //
86 // - As a return value for functions that may fail to return a value on all
87 //   allowed inputs. For example, a function that searches an array might
88 //   return an Optional<size_t> (the index where it found the element, or
89 //   nothing if it didn't find it); and a function that parses numbers might
90 //   return Optional<double> (the parsed number, or nothing if parsing failed).
91 //
92 // Examples of bad places to use Optional:
93 //
94 // - As a return value for functions that may fail because of disallowed
95 //   inputs. For example, a string length function should not return
96 //   Optional<size_t> so that it can return nothing in case the caller passed
97 //   it a null pointer; the function should probably use RTC_[D]CHECK instead,
98 //   and return plain size_t.
99 //
100 // - As a return value for functions that may fail to return a value on all
101 //   allowed inputs, but need to tell the caller what went wrong. Returning
102 //   Optional<double> when parsing a single number as in the example above
103 //   might make sense, but any larger parse job is probably going to need to
104 //   tell the caller what the problem was, not just that there was one.
105 //
106 // - As a non-mutable function argument. When you want to pass a value of a
107 //   type T that can fail to be there, const T* is almost always both fastest
108 //   and cleanest. (If you're *sure* that the the caller will always already
109 //   have an Optional<T>, const Optional<T>& is slightly faster than const T*,
110 //   but this is a micro-optimization. In general, stick to const T*.)
111 //
112 // TODO(kwiberg): Get rid of this class when the standard library has
113 // std::optional (and we're allowed to use it).
114 template <typename T>
115 class Optional final {
116  public:
117   // Construct an empty Optional.
Optional()118   Optional() : has_value_(false), empty_('\0') { PoisonValue(); }
119 
Optional(rtc::nullopt_t)120   Optional(rtc::nullopt_t)  // NOLINT(runtime/explicit)
121       : Optional() {}
122 
123   // Construct an Optional that contains a value.
Optional(const T & value)124   Optional(const T& value)  // NOLINT(runtime/explicit)
125       : has_value_(true) {
126     new (&value_) T(value);
127   }
Optional(T && value)128   Optional(T&& value)  // NOLINT(runtime/explicit)
129       : has_value_(true) {
130     new (&value_) T(std::move(value));
131   }
132 
133   // Copy constructor: copies the value from m if it has one.
Optional(const Optional & m)134   Optional(const Optional& m) : has_value_(m.has_value_) {
135     if (has_value_)
136       new (&value_) T(m.value_);
137     else
138       PoisonValue();
139   }
140 
141   // Move constructor: if m has a value, moves the value from m, leaving m
142   // still in a state where it has a value, but a moved-from one (the
143   // properties of which depends on T; the only general guarantee is that we
144   // can destroy m).
Optional(Optional && m)145   Optional(Optional&& m) : has_value_(m.has_value_) {
146     if (has_value_)
147       new (&value_) T(std::move(m.value_));
148     else
149       PoisonValue();
150   }
151 
~Optional()152   ~Optional() {
153     if (has_value_)
154       value_.~T();
155     else
156       UnpoisonValue();
157   }
158 
159   Optional& operator=(rtc::nullopt_t) {
160     reset();
161     return *this;
162   }
163 
164   // Copy assignment. Uses T's copy assignment if both sides have a value, T's
165   // copy constructor if only the right-hand side has a value.
166   Optional& operator=(const Optional& m) {
167     if (m.has_value_) {
168       if (has_value_) {
169         value_ = m.value_;  // T's copy assignment.
170       } else {
171         UnpoisonValue();
172         new (&value_) T(m.value_);  // T's copy constructor.
173         has_value_ = true;
174       }
175     } else {
176       reset();
177     }
178     return *this;
179   }
180 
181   // Move assignment. Uses T's move assignment if both sides have a value, T's
182   // move constructor if only the right-hand side has a value. The state of m
183   // after it's been moved from is as for the move constructor.
184   Optional& operator=(Optional&& m) {
185     if (m.has_value_) {
186       if (has_value_) {
187         value_ = std::move(m.value_);  // T's move assignment.
188       } else {
189         UnpoisonValue();
190         new (&value_) T(std::move(m.value_));  // T's move constructor.
191         has_value_ = true;
192       }
193     } else {
194       reset();
195     }
196     return *this;
197   }
198 
199   // Swap the values if both m1 and m2 have values; move the value if only one
200   // of them has one.
swap(Optional & m1,Optional & m2)201   friend void swap(Optional& m1, Optional& m2) {
202     if (m1.has_value_) {
203       if (m2.has_value_) {
204         // Both have values: swap.
205         using std::swap;
206         swap(m1.value_, m2.value_);
207       } else {
208         // Only m1 has a value: move it to m2.
209         m2.UnpoisonValue();
210         new (&m2.value_) T(std::move(m1.value_));
211         m1.value_.~T();  // Destroy the moved-from value.
212         m1.has_value_ = false;
213         m2.has_value_ = true;
214         m1.PoisonValue();
215       }
216     } else if (m2.has_value_) {
217       // Only m2 has a value: move it to m1.
218       m1.UnpoisonValue();
219       new (&m1.value_) T(std::move(m2.value_));
220       m2.value_.~T();  // Destroy the moved-from value.
221       m1.has_value_ = true;
222       m2.has_value_ = false;
223       m2.PoisonValue();
224     }
225   }
226 
227   // Destroy any contained value. Has no effect if we have no value.
reset()228   void reset() {
229     if (!has_value_)
230       return;
231     value_.~T();
232     has_value_ = false;
233     PoisonValue();
234   }
235 
236   template <class... Args>
emplace(Args &&...args)237   void emplace(Args&&... args) {
238     if (has_value_)
239       value_.~T();
240     else
241       UnpoisonValue();
242     new (&value_) T(std::forward<Args>(args)...);
243     has_value_ = true;
244   }
245 
246   // Conversion to bool to test if we have a value.
247   explicit operator bool() const { return has_value_; }
has_value()248   bool has_value() const { return has_value_; }
249 
250   // Dereferencing. Only allowed if we have a value.
251   const T* operator->() const {
252     RTC_DCHECK(has_value_);
253     return &value_;
254   }
255   T* operator->() {
256     RTC_DCHECK(has_value_);
257     return &value_;
258   }
259   const T& operator*() const {
260     RTC_DCHECK(has_value_);
261     return value_;
262   }
263   T& operator*() {
264     RTC_DCHECK(has_value_);
265     return value_;
266   }
value()267   const T& value() const {
268     RTC_DCHECK(has_value_);
269     return value_;
270   }
value()271   T& value() {
272     RTC_DCHECK(has_value_);
273     return value_;
274   }
275 
276   // Dereference with a default value in case we don't have a value.
value_or(const T & default_val)277   const T& value_or(const T& default_val) const {
278     // The no-op call prevents the compiler from generating optimized code that
279     // reads value_ even if !has_value_, but only if FunctionThatDoesNothing is
280     // not completely inlined; see its declaration.).
281     return has_value_ ? *optional_internal::FunctionThatDoesNothing(&value_)
282                       : default_val;
283   }
284 
285   // Dereference and move value.
MoveValue()286   T MoveValue() {
287     RTC_DCHECK(has_value_);
288     return std::move(value_);
289   }
290 
291   // Equality tests. Two Optionals are equal if they contain equivalent values,
292   // or if they're both empty.
293   friend bool operator==(const Optional& m1, const Optional& m2) {
294     return m1.has_value_ && m2.has_value_ ? m1.value_ == m2.value_
295                                           : m1.has_value_ == m2.has_value_;
296   }
297   friend bool operator==(const Optional& opt, const T& value) {
298     return opt.has_value_ && opt.value_ == value;
299   }
300   friend bool operator==(const T& value, const Optional& opt) {
301     return opt.has_value_ && value == opt.value_;
302   }
303 
304   friend bool operator==(const Optional& opt, rtc::nullopt_t) {
305     return !opt.has_value_;
306   }
307 
308   friend bool operator==(rtc::nullopt_t, const Optional& opt) {
309     return !opt.has_value_;
310   }
311 
312   friend bool operator!=(const Optional& m1, const Optional& m2) {
313     return m1.has_value_ && m2.has_value_ ? m1.value_ != m2.value_
314                                           : m1.has_value_ != m2.has_value_;
315   }
316   friend bool operator!=(const Optional& opt, const T& value) {
317     return !opt.has_value_ || opt.value_ != value;
318   }
319   friend bool operator!=(const T& value, const Optional& opt) {
320     return !opt.has_value_ || value != opt.value_;
321   }
322 
323   friend bool operator!=(const Optional& opt, rtc::nullopt_t) {
324     return opt.has_value_;
325   }
326 
327   friend bool operator!=(rtc::nullopt_t, const Optional& opt) {
328     return opt.has_value_;
329   }
330 
331  private:
332   // Tell sanitizers that value_ shouldn't be touched.
PoisonValue()333   void PoisonValue() {
334     rtc::AsanPoison(rtc::MakeArrayView(&value_, 1));
335     rtc::MsanMarkUninitialized(rtc::MakeArrayView(&value_, 1));
336   }
337 
338   // Tell sanitizers that value_ is OK to touch again.
UnpoisonValue()339   void UnpoisonValue() { rtc::AsanUnpoison(rtc::MakeArrayView(&value_, 1)); }
340 
341   bool has_value_;  // True iff value_ contains a live value.
342   union {
343     // empty_ exists only to make it possible to initialize the union, even when
344     // it doesn't contain any data. If the union goes uninitialized, it may
345     // trigger compiler warnings.
346     char empty_;
347     // By placing value_ in a union, we get to manage its construction and
348     // destruction manually: the Optional constructors won't automatically
349     // construct it, and the Optional destructor won't automatically destroy
350     // it. Basically, this just allocates a properly sized and aligned block of
351     // memory in which we can manually put a T with placement new.
352     T value_;
353   };
354 };
355 
356 #ifdef UNIT_TEST
357 namespace optional_internal {
358 
359 // Checks if there's a valid PrintTo(const T&, std::ostream*) call for T.
360 template <typename T>
361 struct HasPrintTo {
362  private:
363   struct No {};
364 
365   template <typename T2>
366   static auto Test(const T2& obj)
367       -> decltype(PrintTo(obj, std::declval<std::ostream*>()));
368 
369   template <typename>
370   static No Test(...);
371 
372  public:
373   static constexpr bool value =
374       !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
375 };
376 
377 // Checks if there's a valid operator<<(std::ostream&, const T&) call for T.
378 template <typename T>
379 struct HasOstreamOperator {
380  private:
381   struct No {};
382 
383   template <typename T2>
384   static auto Test(const T2& obj)
385       -> decltype(std::declval<std::ostream&>() << obj);
386 
387   template <typename>
388   static No Test(...);
389 
390  public:
391   static constexpr bool value =
392       !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value;
393 };
394 
395 // Prefer using PrintTo to print the object.
396 template <typename T>
OptionalPrintToHelper(const T & value,std::ostream * os)397 typename std::enable_if<HasPrintTo<T>::value, void>::type OptionalPrintToHelper(
398     const T& value,
399     std::ostream* os) {
400   PrintTo(value, os);
401 }
402 
403 // Fall back to operator<<(std::ostream&, ...) if it exists.
404 template <typename T>
405 typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
406                         void>::type
OptionalPrintToHelper(const T & value,std::ostream * os)407 OptionalPrintToHelper(const T& value, std::ostream* os) {
408   *os << value;
409 }
410 
OptionalPrintObjectBytes(const unsigned char * bytes,size_t size,std::ostream * os)411 inline void OptionalPrintObjectBytes(const unsigned char* bytes,
412                                      size_t size,
413                                      std::ostream* os) {
414   *os << "<optional with " << size << "-byte object [";
415   for (size_t i = 0; i != size; ++i) {
416     *os << (i == 0 ? "" : ((i & 1) ? "-" : " "));
417     *os << std::hex << std::setw(2) << std::setfill('0')
418         << static_cast<int>(bytes[i]);
419   }
420   *os << "]>";
421 }
422 
423 // As a final back-up, just print the contents of the objcets byte-wise.
424 template <typename T>
425 typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value,
426                         void>::type
OptionalPrintToHelper(const T & value,std::ostream * os)427 OptionalPrintToHelper(const T& value, std::ostream* os) {
428   OptionalPrintObjectBytes(reinterpret_cast<const unsigned char*>(&value),
429                            sizeof(value), os);
430 }
431 
432 }  // namespace optional_internal
433 
434 // PrintTo is used by gtest to print out the results of tests. We want to ensure
435 // the object contained in an Optional can be printed out if it's set, while
436 // avoiding touching the object's storage if it is undefined.
437 template <typename T>
PrintTo(const rtc::Optional<T> & opt,std::ostream * os)438 void PrintTo(const rtc::Optional<T>& opt, std::ostream* os) {
439   if (opt) {
440     optional_internal::OptionalPrintToHelper(*opt, os);
441   } else {
442     *os << "<empty optional>";
443   }
444 }
445 
446 #endif  // UNIT_TEST
447 
448 }  // namespace rtc
449 
450 #endif  // API_OPTIONAL_H_
451