SST 15.0
Structural Simulation Toolkit
from_string.h
1// Copyright 2009-2025 NTESS. Under the terms
2// of Contract DE-NA0003525 with NTESS, the U.S.
3// Government retains certain rights in this software.
4//
5// Copyright (c) 2009-2025, NTESS
6// All rights reserved.
7//
8// This file is part of the SST software package. For license
9// information, see the LICENSE file in the top level directory of the
10// distribution.
11
12#ifndef SST_CORE_FROM_STRING_H
13#define SST_CORE_FROM_STRING_H
14
15#include <stdexcept>
16#include <string>
17#include <type_traits>
18
19namespace SST::Core {
20
21template <class T>
22std::enable_if_t<std::is_integral_v<T>, T>
23from_string(const std::string& input)
24{
25 if constexpr ( std::is_signed_v<T> ) {
26 if constexpr ( std::is_same_v<int, T> ) {
27 return std::stoi(input, nullptr, 0);
28 }
29 else if constexpr ( std::is_same_v<long, T> ) {
30 return std::stol(input, nullptr, 0);
31 }
32 else if constexpr ( std::is_same_v<long long, T> ) {
33 return std::stoll(input, nullptr, 0);
34 }
35 else { // Smaller than 32-bit
36 return static_cast<T>(std::stol(input, nullptr, 0));
37 }
38 }
39 else {
40 if constexpr ( std::is_same_v<bool, T> ) {
41 // valid pairs: true/false, t/f, yes/no, y/n, on/off, 1/0
42 std::string transform(input);
43 for ( auto& c : transform )
44 c = std::tolower(c);
45 if ( transform == "true" || transform == "t" || transform == "yes" || transform == "y" ||
46 transform == "on" || transform == "1" ) {
47 return true;
48 }
49 else if ( transform == "false" || transform == "f" || transform == "no" || transform == "n" ||
50 transform == "off" || transform == "0" ) {
51 return false;
52 }
53 else {
54 throw std::invalid_argument("from_string: no valid conversion");
55 }
56 }
57 else if constexpr ( std::is_same_v<unsigned long, T> ) {
58 return std::stoul(input, nullptr, 0);
59 }
60 else if constexpr ( std::is_same_v<unsigned long long, T> ) {
61 return std::stoull(input, nullptr, 0);
62 }
63 else { // Smaller than 32-bit
64 return static_cast<T>(std::stoul(input, nullptr, 0));
65 }
66 }
67}
68
69template <class T>
70std::enable_if_t<std::is_floating_point_v<T>, T>
71from_string(const std::string& input)
72{
73 if constexpr ( std::is_same_v<float, T> ) {
74 return stof(input);
75 }
76 else if constexpr ( std::is_same_v<double, T> ) {
77 return stod(input);
78 }
79 else if constexpr ( std::is_same_v<long double, T> ) {
80 return stold(input);
81 }
82 else { // make compiler happy
83 return stod(input);
84 }
85}
86
87template <class T>
88std::enable_if_t<std::is_class_v<T>, T>
89from_string(const std::string& input)
90{
91 static_assert(std::is_constructible_v<T, std::string>,
92 "ERROR: from_string can only be used with integral and floating point types and with classes that have a "
93 "constructor that takes a single string as input.\n");
94 return T(input);
95}
96
97template <class T>
98std::enable_if_t<std::is_enum_v<T>, T>
99from_string(const std::string& input)
100{
101 return static_cast<T>(from_string<std::underlying_type_t<T>>(input));
102}
103
104///////////////////////////////////////////////////////////////////////////////
105
106template <class T>
107std::enable_if_t<!std::is_enum_v<T>, std::string>
108to_string(const T& input)
109{
110 if constexpr ( std::is_arithmetic_v<T> )
111 return std::to_string(input);
112 else
113 return typeid(T).name(); // For now, return a string if the type isn't handled elsewhere
114}
115
116template <class T>
117std::enable_if_t<std::is_enum_v<T>, std::string>
118to_string(const T& input)
119{
120 return std::to_string(static_cast<std::underlying_type_t<T>>(input));
121}
122
123// for std::string no-op, or class types which define operator std::string()
124inline std::string
125to_string(std::string s)
126{
127 return s;
128}
129
130} // end namespace SST::Core
131
132#endif // SST_CORE_FROM_STRING_H