Chromium Code Reviews| 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 | |
|
kwiberg-webrtc
2017/02/18 18:50:47
Who defines this? I couldn't find it in our tree.
kjellander_webrtc
2017/02/19 09:29:19
It comes from gtest: https://cs.chromium.org/chrom
kwiberg-webrtc
2017/02/19 13:14:15
Aha. Excellent!
kjellander_webrtc
2017/02/20 07:24:20
I don't have time to put in more work than this fo
| |
| 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 |
| 44 template <typename T> | |
| 45 inline const T* FunctionThatDoesNothing(const T* x) { | |
| 46 return const_cast<const T*>(reinterpret_cast<T*>( | |
| 47 FunctionThatDoesNothingImpl(reinterpret_cast<void*>(const_cast<T*>(x))))); | |
|
kwiberg-webrtc
2017/02/18 18:50:47
The outermost const_cast is unnecessary.
ossu
2017/02/20 11:02:24
That is true. But also, I think the whole function
kwiberg-webrtc
2017/02/20 11:45:31
Acknowledged.
| |
| 48 } | |
| 49 | |
| 37 #else | 50 #else |
| 38 | 51 |
| 39 template <typename T> | 52 template <typename T> |
| 40 inline T* FunctionThatDoesNothing(T* x) { return x; } | 53 inline T* FunctionThatDoesNothing(T* x) { return x; } |
| 41 | 54 |
| 42 #endif | 55 #endif |
| 43 | 56 |
| 44 } // namespace optional_internal | 57 } // namespace optional_internal |
| 45 | 58 |
| 46 // Simple std::optional-wannabe. It either contains a T or not. | 59 // Simple std::optional-wannabe. It either contains a T or not. |
| (...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 char empty_; | 302 char empty_; |
| 290 // By placing value_ in a union, we get to manage its construction and | 303 // By placing value_ in a union, we get to manage its construction and |
| 291 // destruction manually: the Optional constructors won't automatically | 304 // destruction manually: the Optional constructors won't automatically |
| 292 // construct it, and the Optional destructor won't automatically destroy | 305 // construct it, and the Optional destructor won't automatically destroy |
| 293 // it. Basically, this just allocates a properly sized and aligned block of | 306 // 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. | 307 // memory in which we can manually put a T with placement new. |
| 295 T value_; | 308 T value_; |
| 296 }; | 309 }; |
| 297 }; | 310 }; |
| 298 | 311 |
| 312 #ifdef UNIT_TEST | |
| 313 namespace optional_internal { | |
| 314 | |
| 315 // Checks if there's a valid PrintTo(const T&, std::ostream*) call for T. | |
| 316 template <typename T> | |
| 317 struct HasPrintTo { | |
| 318 private: | |
| 319 struct No {}; | |
| 320 | |
| 321 template <typename T2> | |
| 322 static auto Test(const T2& obj) | |
| 323 -> decltype(PrintTo(obj, std::declval<std::ostream*>())); | |
| 324 | |
| 325 template <typename> | |
| 326 static No Test(...); | |
| 327 | |
| 328 public: | |
| 329 static constexpr bool value = | |
| 330 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value; | |
| 331 }; | |
| 332 | |
| 333 // Checks if there's a valid operator<<(std::ostream&, const T&) call for T. | |
| 334 template <typename T> | |
| 335 struct HasOstreamOperator { | |
| 336 private: | |
| 337 struct No {}; | |
| 338 | |
| 339 template <typename T2> | |
| 340 static auto Test(const T2& obj) | |
| 341 -> decltype(std::declval<std::ostream&>() << obj); | |
| 342 | |
| 343 template <typename> | |
| 344 static No Test(...); | |
| 345 | |
| 346 public: | |
| 347 static constexpr bool value = | |
| 348 !std::is_same<decltype(Test<T>(std::declval<const T&>())), No>::value; | |
| 349 }; | |
| 350 | |
| 351 // Prefer using PrintTo to print the object. | |
| 352 template <typename T> | |
| 353 typename std::enable_if<HasPrintTo<T>::value, void>::type OptionalPrintToHelper( | |
| 354 const T& value, | |
| 355 std::ostream* os) { | |
| 356 PrintTo(value, os); | |
| 357 } | |
| 358 | |
| 359 // Fall back to operator<<(std::ostream&, ...) if it exists. | |
| 360 template <typename T> | |
| 361 typename std::enable_if<HasOstreamOperator<T>::value && !HasPrintTo<T>::value, | |
| 362 void>::type | |
| 363 OptionalPrintToHelper(const T& value, std::ostream* os) { | |
| 364 *os << value; | |
| 365 } | |
| 366 | |
| 367 inline void OptionalPrintObjectBytes(const unsigned char* bytes, | |
| 368 size_t size, | |
| 369 std::ostream* os) { | |
| 370 *os << "<optional with " << size << "-byte object ["; | |
| 371 for (size_t i = 0; i != size; ++i) { | |
| 372 *os << (i == 0 ? "" : ((i & 1) ? "-" : " ")); | |
| 373 *os << std::hex << std::setw(2) << std::setfill('0') | |
| 374 << static_cast<int>(bytes[i]); | |
| 375 } | |
| 376 *os << "]>"; | |
| 377 } | |
| 378 | |
| 379 // As a final back-up, just print the contents of the objcets byte-wise. | |
| 380 template <typename T> | |
| 381 typename std::enable_if<!HasOstreamOperator<T>::value && !HasPrintTo<T>::value, | |
| 382 void>::type | |
| 383 OptionalPrintToHelper(const T& value, std::ostream* os) { | |
| 384 OptionalPrintObjectBytes(reinterpret_cast<const unsigned char*>(&value), | |
| 385 sizeof(value), os); | |
| 386 } | |
| 387 | |
| 388 } // namespace optional_internal | |
| 389 | |
| 390 // PrintTo is used by gtest to print out the results of tests. We want to ensure | |
| 391 // the object contained in an Optional can be printed out if it's set, while | |
| 392 // avoiding touching the object's storage if it is undefined. | |
| 393 template <typename T> | |
| 394 void PrintTo(const rtc::Optional<T>& opt, std::ostream* os) { | |
| 395 if (opt) { | |
| 396 optional_internal::OptionalPrintToHelper(*opt, os); | |
| 397 } else { | |
| 398 *os << "<empty optional>"; | |
| 399 } | |
| 400 } | |
| 401 | |
| 402 #endif // UNIT_TEST | |
| 403 | |
| 299 } // namespace rtc | 404 } // namespace rtc |
| 300 | 405 |
| 301 #endif // WEBRTC_BASE_OPTIONAL_H_ | 406 #endif // WEBRTC_BASE_OPTIONAL_H_ |
| OLD | NEW |