Audacity 3.2.0
Functions
anonymous_namespace{FromChars.cpp} Namespace Reference

Functions

unsigned digitToInt (char c) noexcept
 
template<typename T >
bool safeMul10Add (T &result, T a, T b)
 
template<typename ResultType >
FromCharsResult FastStringToInt (const char *first, const char *last, ResultType &value, bool isNegative) noexcept
 
template<typename ResultType >
FromCharsResult IntFromChars (const char *buffer, const char *last, ResultType &value) noexcept
 

Function Documentation

◆ digitToInt()

unsigned anonymous_namespace{FromChars.cpp}::digitToInt ( char  c)
noexcept

Definition at line 21 of file FromChars.cpp.

22{
23 return static_cast<unsigned>(c) - '0';
24}

Referenced by FastStringToInt().

Here is the caller graph for this function:

◆ FastStringToInt()

template<typename ResultType >
FromCharsResult anonymous_namespace{FromChars.cpp}::FastStringToInt ( const char *  first,
const char *  last,
ResultType &  value,
bool  isNegative 
)
noexcept

Definition at line 58 of file FromChars.cpp.

61{
62 using UnsignedResultType = std::make_unsigned_t<ResultType>;
63
64 const auto availableBytes = last - first;
65
66 if (availableBytes <= 0)
67 return { first, std::errc::invalid_argument };
68
69 UnsignedResultType result = digitToInt(*first);
70
71 if (result > 10)
72 return { first, std::errc::invalid_argument };
73
74 constexpr auto maxSafeDigits = std::numeric_limits<ResultType>::digits10;
75
76 const char* ptr = first;
77 const char* safeLast =
78 first + std::min<decltype(availableBytes)>(availableBytes, maxSafeDigits);
79
80 unsigned d;
81
82 // No integer overflow here
83 while (++ptr < safeLast && (d = digitToInt(*ptr)) <= 9)
84 {
85 result = result * 10 + d;
86 }
87
88 // But here live dragons
89 while (ptr < last && (d = digitToInt(*ptr)) <= 9)
90 {
91 if (!safeMul10Add<UnsignedResultType>(result, result, d))
92 return { ptr, std::errc::result_out_of_range };
93
94 // Even if there were no unsigned overflow,
95 // signed overflow is still possible
96 if constexpr (std::is_signed_v<ResultType>)
97 {
98 const UnsignedResultType max =
99 static_cast<UnsignedResultType>(
100 std::numeric_limits<ResultType>::max()) +
101 (isNegative ? 1 : 0);
102
103 if (result > max)
104 return { ptr, std::errc::result_out_of_range };
105 }
106
107
108 ++ptr;
109 }
110
111 if constexpr (std::is_signed_v<ResultType>)
112 {
113 value = isNegative ?
114 // Unary minus on unsigned type makes MSVC unhappy
115 static_cast<ResultType>(0 - result) :
116 static_cast<ResultType>(result);
117 }
118 else
119 value = static_cast<ResultType>(result);
120
121 return { ptr, std::errc() };
122}
unsigned digitToInt(char c) noexcept
Definition: FromChars.cpp:21

References digitToInt().

Referenced by IntFromChars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ IntFromChars()

template<typename ResultType >
FromCharsResult anonymous_namespace{FromChars.cpp}::IntFromChars ( const char *  buffer,
const char *  last,
ResultType &  value 
)
noexcept

Definition at line 126 of file FromChars.cpp.

127{
128 const char* origin = buffer;
129
130 if (buffer >= last)
131 return { buffer, std::errc::invalid_argument };
132
133 const bool isNegative = *buffer == '-';
134
135 if (isNegative)
136 {
137 if constexpr (std::is_signed_v<ResultType>)
138 ++buffer;
139 else
140 return { origin, std::errc::invalid_argument };
141 }
142
143 const auto fastStringResult =
144 FastStringToInt(buffer, last, value, isNegative);
145
146 if (fastStringResult.ec == std::errc::invalid_argument)
147 return { origin, std::errc::invalid_argument };
148
149 return fastStringResult;
150}
FromCharsResult FastStringToInt(const char *first, const char *last, ResultType &value, bool isNegative) noexcept
Definition: FromChars.cpp:58

References FastStringToInt().

Referenced by FromChars().

Here is the call graph for this function:
Here is the caller graph for this function:

◆ safeMul10Add()

template<typename T >
bool anonymous_namespace{FromChars.cpp}::safeMul10Add ( T &  result,
a,
b 
)

Definition at line 27 of file FromChars.cpp.

28{
29 static_assert(std::is_unsigned_v<T>);
30
31 constexpr auto bits = sizeof(a) * 8 - 3;
32 // Check for the top 3 bits of a
33 if (a >> bits)
34 return false;
35
36 const T times8 = a << 3;
37 // a << 1 won't overflow
38 const T times2 = a << 1;
39
40 // timesX are all unsigned values, if overflow occurs - times10 will be <
41 // times8
42 const T times10 = times8 + times2;
43
44 if (times10 < times8)
45 return false;
46
47 const T tempResult = times10 + b;
48
49 if (tempResult < times10)
50 return false;
51
52 result = tempResult;
53
54 return true;
55}