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 |