OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2015 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 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 | 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 | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 #ifndef WEBRTC_BASE_OPTIONAL_H_ | 11 #ifndef WEBRTC_BASE_OPTIONAL_H_ |
12 #define WEBRTC_BASE_OPTIONAL_H_ | 12 #define WEBRTC_BASE_OPTIONAL_H_ |
13 | 13 |
14 #include <algorithm> | 14 #include <algorithm> |
15 #include <memory> | 15 #include <memory> |
16 #include <utility> | 16 #include <utility> |
17 | 17 |
| 18 #ifdef UNIT_TEST |
| 19 #include <iomanip> |
| 20 #include <ostream> |
| 21 #endif // UNIT_TEST |
| 22 |
18 #include "webrtc/base/array_view.h" | 23 #include "webrtc/base/array_view.h" |
19 #include "webrtc/base/checks.h" | 24 #include "webrtc/base/checks.h" |
20 #include "webrtc/base/sanitizer.h" | 25 #include "webrtc/base/sanitizer.h" |
21 | 26 |
22 namespace rtc { | 27 namespace rtc { |
23 | 28 |
24 namespace optional_internal { | 29 namespace optional_internal { |
25 | 30 |
26 #if RTC_HAS_ASAN | 31 #if RTC_HAS_ASAN |
27 | 32 |
28 // This is a non-inlined function. The optimizer can't see inside it. | 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. |
29 void* FunctionThatDoesNothingImpl(void*); | 36 void* FunctionThatDoesNothingImpl(void*); |
30 | 37 |
31 template <typename T> | 38 template <typename T> |
32 inline T* FunctionThatDoesNothing(T* x) { | 39 inline T* FunctionThatDoesNothing(T* x) { |
33 return reinterpret_cast<T*>( | 40 return reinterpret_cast<T*>( |
34 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x))); | 41 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(x))); |
35 } | 42 } |
36 | 43 |
37 #else | 44 #else |
38 | 45 |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 char empty_; | 296 char empty_; |
290 // By placing value_ in a union, we get to manage its construction and | 297 // By placing value_ in a union, we get to manage its construction and |
291 // destruction manually: the Optional constructors won't automatically | 298 // destruction manually: the Optional constructors won't automatically |
292 // construct it, and the Optional destructor won't automatically destroy | 299 // construct it, and the Optional destructor won't automatically destroy |
293 // it. Basically, this just allocates a properly sized and aligned block of | 300 // it. Basically, this just allocates a properly sized and aligned block of |
294 // memory in which we can manually put a T with placement new. | 301 // memory in which we can manually put a T with placement new. |
295 T value_; | 302 T value_; |
296 }; | 303 }; |
297 }; | 304 }; |
298 | 305 |
| 306 #ifdef UNIT_TEST |
| 307 namespace optional_internal { |
| 308 |
| 309 // Checks if there's a valid PrintTo(const T&, std::ostream*) call for T. |
| 310 template <typename T> |
| 311 struct 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. |
| 328 template <typename T> |
| 329 struct 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. |
| 346 template <typename T> |
| 347 typename 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. |
| 354 template <typename T> |
| 355 typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value, |
| 356 void>::type |
| 357 OptionalPrintToHelper(const T& value, std::ostream* os) { |
| 358 *os << value; |
| 359 } |
| 360 |
| 361 inline 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. |
| 374 template <typename T> |
| 375 typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value, |
| 376 void>::type |
| 377 OptionalPrintToHelper(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. |
| 387 template <typename T> |
| 388 void 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 |
299 } // namespace rtc | 398 } // namespace rtc |
300 | 399 |
301 #endif // WEBRTC_BASE_OPTIONAL_H_ | 400 #endif // WEBRTC_BASE_OPTIONAL_H_ |
OLD | NEW |