1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
#ifndef CAST_INL_H_
#error "Direct inclusion of this file is not allowed, include cast.h"
// For the sake of sane code completion.
#include "cast.h"
#endif
#include <util/string/cast.h>
#include <util/string/printf.h>
#include <type_traits>
namespace NYT {
////////////////////////////////////////////////////////////////////////////////
namespace NDetail {
template <class T, class S>
typename std::enable_if<std::is_signed<T>::value && std::is_signed<S>::value, bool>::type IsInIntegralRange(S value)
{
return value >= std::numeric_limits<T>::min() && value <= std::numeric_limits<T>::max();
}
template <class T, class S>
static typename std::enable_if<std::is_signed<T>::value && std::is_unsigned<S>::value, bool>::type IsInIntegralRange(S value)
{
return value <= static_cast<typename std::make_unsigned<T>::type>(std::numeric_limits<T>::max());
}
template <class T, class S>
static typename std::enable_if<std::is_unsigned<T>::value && std::is_signed<S>::value, bool>::type IsInIntegralRange(S value)
{
return value >= 0 && static_cast<typename std::make_unsigned<S>::type>(value) <= std::numeric_limits<T>::max();
}
template <class T, class S>
typename std::enable_if<std::is_unsigned<T>::value && std::is_unsigned<S>::value, bool>::type IsInIntegralRange(S value)
{
return value <= std::numeric_limits<T>::max();
}
template <class T>
TString FormatInvalidCastValue(T value)
{
return ::ToString(value);
}
inline TString FormatInvalidCastValue(signed char value)
{
return TString("'") + value + TString("'");
}
inline TString FormatInvalidCastValue(unsigned char value)
{
return TString("'") + value + TString("'");
}
#ifdef __cpp_char8_t
inline TString FormatInvalidCastValue(char8_t value)
{
return FormatInvalidCastValue(static_cast<unsigned char>(value));
}
#endif
} // namespace NDetail
template <class T, class S>
bool TryIntegralCast(S value, T* result)
{
if (!NYT::NDetail::IsInIntegralRange<T>(value)) {
return false;
}
*result = static_cast<T>(value);
return true;
}
template <class T, class S>
T CheckedIntegralCast(S value)
{
T result;
if (!TryIntegralCast<T>(value, &result)) {
throw TSimpleException(Sprintf("Argument value %s is out of expected range",
NYT::NDetail::FormatInvalidCastValue(value).c_str()));
}
return result;
}
template <class T, class S>
bool TryEnumCast(S value, T* result)
{
auto candidate = static_cast<T>(value);
if (!TEnumTraits<T>::FindLiteralByValue(candidate)) {
return false;
}
*result = candidate;
return true;
}
template <class T, class S>
T CheckedEnumCast(S value)
{
T result;
if (!TryEnumCast<T>(value, &result)) {
throw TSimpleException(Sprintf("Invalid value %d of enum type %s",
static_cast<int>(value),
TEnumTraits<T>::GetTypeName().data()));
}
return result;
}
////////////////////////////////////////////////////////////////////////////////
} // namespace NYT
|