USRP Hardware Driver and Device Manual Version: 4.10.0.0_release
UHD and USRP Manual
Loading...
Searching...
No Matches
cast.hpp
Go to the documentation of this file.
1//
2// Copyright 2014-2015 Ettus Research LLC
3// Copyright 2018 Ettus Research, a National Instruments Company
4// Copyright 2019 Ettus Research, a National Instruments Brand
5//
6// SPDX-License-Identifier: GPL-3.0-or-later
7//
8
9#pragma once
10
11#include <uhd/config.hpp>
12#include <uhd/exception.hpp>
13#include <type_traits>
14#include <complex>
15#include <cstdint>
16#include <iomanip>
17#include <ios>
18#include <limits>
19#include <locale>
20#include <sstream>
21#include <string>
22
23namespace uhd { namespace cast {
25//
26// Example:
27// uint16_t x = hexstr_cast<uint16_t>("0xDEADBEEF");
28// Uses stringstream.
29template <typename T>
30inline T hexstr_cast(const std::string& in)
31{
32 T x;
33 std::stringstream ss;
34 ss << std::hex << in;
35 ss >> x;
36 return x;
37}
38
41//
42// Example:
43// 10, 0x10, 010 get parsed to decimal 10, 16, 8.
44// uint32_t x = fromstr_cast<uint32_t>("0xaffe");
45// Uses istringstream.
46template <typename T>
47inline T fromstr_cast(const std::string& in)
48{
49 T x;
50 std::istringstream is(in);
51 is >> std::setbase(0) >> x;
52 return x;
53}
54
56//
57// Handles size_t aliases (unsigned long, unsigned long long) via if constexpr
58// when they are not the same type as uint32_t or uint64_t.
59// Explicit specializations below override this for bool, double, int,
60// uint32_t, uint64_t, uint16_t, uint8_t, and std::string.
61//
62// Note that we need this generic template to handle arbitrary types at runtime.
63// However, this means we can't use SFINAE to create template specializations,
64// which means any type that requires template logic needs to go into here and
65// must be explicitly handled with if constexpr.
66template <typename data_t>
67data_t from_str(const std::string& val)
68{
69 if constexpr (
70 (std::is_same_v<data_t,
71 size_t> || std::is_same_v<data_t, unsigned long> || std::is_same_v<data_t, unsigned long long>)&&!std::
72 is_same_v<data_t, uint32_t> && !std::is_same_v<data_t, uint64_t>) {
73 try {
74 if (!val.empty() && val[0] == '-') {
75 throw std::out_of_range("negative value for unsigned type");
76 }
77 size_t pos;
78 unsigned long long tmp = std::stoull(val, &pos);
79 if (pos != val.length()) {
80 throw std::invalid_argument("trailing characters");
81 }
82 if (tmp > std::numeric_limits<data_t>::max()) {
83 throw std::out_of_range("value out of range");
84 }
85 return static_cast<data_t>(tmp);
86 } catch (std::invalid_argument&) {
88 std::string("Cannot convert `") + val + "' to numeric type!");
89 } catch (std::out_of_range&) {
91 std::string("Cannot convert `") + val + "' to numeric type!");
92 }
93 } else {
94 throw uhd::runtime_error("Cannot convert from string!");
95 }
96}
97
98// Specializations of `uhd::cast::from_str()` for supported data types
99
101//
102// Examples evaluating to `true`: 'True', 'Yes', 'y', '1', empty string
103// Examples evaluating to `false`: 'false', 'NO', 'n', '0'
104// Throws `uhd::runtime_error` if the string can't be converted to `bool`
105template <>
106UHD_API bool from_str(const std::string& val);
107
109template <>
110UHD_API double from_str(const std::string& val);
111
113template <>
114UHD_API int from_str(const std::string& val);
115
117template <>
118UHD_API uint8_t from_str(const std::string& val);
119
121template <>
122UHD_API uint16_t from_str(const std::string& val);
123
125template <>
126UHD_API uint32_t from_str(const std::string& val);
127
129template <>
130UHD_API uint64_t from_str(const std::string& val);
131
133template <>
134inline UHD_API std::string from_str(const std::string& val)
135{
136 return val;
137}
138
140UHD_API std::string to_ordinal_string(int val);
141
143//
144// These template implementations provide consistent string conversion
145// for integer and floating-point types commonly used in UHD, particularly
146// for device_addr_t parameter handling.
147
148// Type trait to detect if a type has a to_string() method
149namespace detail {
150template <typename T>
152 -> decltype(std::declval<T>().to_string(), std::true_type{});
153template <typename T>
154auto has_to_string_method_impl(...) -> std::false_type;
155template <typename T>
157} // namespace detail
158
160//
161// This template will automatically work for integer types that std::to_string supports
162// (int, unsigned int, long, unsigned long, long long, unsigned long long, size_t, etc.),
163// excluding int8_t and uint8_t which need special handling, and floating-point types
164// which need precision handling, and excluding types that have their own to_string()
165// method.
166template <typename T>
167auto to_str(const T& val) -> std::enable_if_t<
168 std::is_arithmetic_v<
169 T> && !std::is_floating_point_v<T> && !std::is_same_v<T, int8_t> && !std::is_same_v<T, uint8_t> && !std::is_enum_v<T> && !detail::has_to_string_method<T>::value,
170 decltype(std::to_string(val))>
171{
172 return std::to_string(val);
173}
174
176//
177// Convert enum types to their underlying integral type, then to string
178template <typename T>
179auto to_str(const T& val) -> std::enable_if_t<std::is_enum_v<T>, std::string>
180{
181 return std::to_string(static_cast<std::underlying_type_t<T>>(val));
182}
183
185//
186// Uses ostringstream with max_digits10 precision and classic locale to ensure
187// round-trip safety for floating-point values.
188template <typename T>
189auto to_str(const T& val) -> std::enable_if_t<
190 std::is_floating_point_v<T> && !detail::has_to_string_method<T>::value,
191 std::string>
192{
193 std::ostringstream oss;
194 oss.imbue(std::locale::classic());
195 oss.precision(std::numeric_limits<T>::max_digits10);
196 oss << val;
197 return oss.str();
198}
199
200// Special handling for int8_t and uint8_t since std::to_string treats them as chars
201
203template <typename T>
204auto to_str(const T& val)
205 -> std::enable_if_t<std::is_same_v<T, int8_t> || std::is_same_v<T, signed char>,
206 std::string>
207{
208 return std::to_string(static_cast<int>(val));
209}
210
212template <typename T>
213auto to_str(const T& val)
214 -> std::enable_if_t<std::is_same_v<T, uint8_t> || std::is_same_v<T, unsigned char>,
215 std::string>
216{
217 return std::to_string(static_cast<unsigned int>(val));
218}
219
221//
222// This template will work for any std::complex<T> where T has a to_str() function
223// Creates a string of the form "a+jb" or "a-jb"
224template <typename T>
225std::string to_str(const std::complex<T>& val)
226{
227 std::string real_str = to_str(val.real());
228 T imag_val = val.imag();
229
230 if (imag_val >= 0) {
231 return real_str + "+j" + to_str(imag_val);
232 } else {
233 return real_str + "-j" + to_str(-imag_val);
234 }
235}
236
238//
239// This template will automatically work for any type T that has a to_string()
240// method that returns a type convertible to std::string.
241template <typename T>
242auto to_str(const T& val)
243 -> std::enable_if_t<std::is_convertible_v<decltype(val.to_string()), std::string>,
244 std::string>
245{
246 return val.to_string();
247}
248
250inline std::string to_str(const std::string& val)
251{
252 return val;
253}
254
255inline std::string to_str(const char* val)
256{
257 return std::string(val);
258}
259
260}} // namespace uhd::cast
#define UHD_API
Definition config.h:87
Template implementations for uhd::cast::to_str() for common types.
Definition cast.hpp:149
auto has_to_string_method_impl(int) -> decltype(std::declval< T >().to_string(), std::true_type{})
decltype(has_to_string_method_impl< T >(0)) has_to_string_method
Definition cast.hpp:156
Definition cast.hpp:23
T fromstr_cast(const std::string &in)
Definition cast.hpp:47
T hexstr_cast(const std::string &in)
Convert a hexadecimal string into a value.
Definition cast.hpp:30
auto to_str(const T &val) -> std::enable_if_t< std::is_arithmetic_v< T > &&!std::is_floating_point_v< T > &&!std::is_same_v< T, int8_t > &&!std::is_same_v< T, uint8_t > &&!std::is_enum_v< T > &&!detail::has_to_string_method< T >::value, decltype(std::to_string(val))>
SFINAE-based template for integer types that std::to_string can handle.
Definition cast.hpp:167
data_t from_str(const std::string &val)
Generic cast-from-string function.
Definition cast.hpp:67
UHD_API std::string to_ordinal_string(int val)
Create an ordinal string from a number.
Definition build_info.hpp:12
Definition exception.hpp:132