KSS Utility
C++ general utilities
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends
convert.hpp
Go to the documentation of this file.
1 //
2 // convert.hpp
3 // kssutil
4 //
5 // Created by Steven W. Klassen on 2018-06-15.
6 // Copyright © 2018 Klassen Software Solutions. All rights reserved.
7 // Licensing follows the MIT License.
8 //
9 
10 #ifndef kssutil_convert_hpp
11 #define kssutil_convert_hpp
12 
13 #include <cerrno>
14 #include <chrono>
15 #include <iostream>
16 #include <stdexcept>
17 #include <sstream>
18 #include <string>
19 #include <system_error>
20 #include <typeinfo>
21 
22 #include "rtti.hpp"
23 
29 namespace kss { namespace util { namespace strings {
30 
36  template <class T>
37  T convert(const std::string& s, const T& = T()) {
38  if (s.empty()) {
39  throw std::invalid_argument("s cannot be empty");
40  }
41 
42  std::istringstream strm(s);
43  T t;
44  strm >> t;
45  if (strm.bad() || strm.fail()) {
46  throw std::system_error(EIO, std::system_category(),
47  "Could not convert '" + s + "'"
48  + " to the type " + kss::util::rtti::name<T>());
49  }
50  return t;
51  }
52 
53  template<>
54  inline std::string convert(const std::string& s, const std::string&) {
55  return s;
56  }
57 
58  // These specializations use implementations from <cstdlib> as they should be
59  // more efficient than using the stream conversions.
60  template<> float convert(const std::string& s, const float&);
61  template<> double convert(const std::string& s, const double&);
62  template<> long double convert(const std::string& s, const long double&);
63  template<> int convert(const std::string& s, const int&);
64  template<> long convert(const std::string& s, const long&);
65  template<> long long convert(const std::string& s, const long long&);
66  template<> unsigned convert(const std::string& s, const unsigned&);
67  template<> unsigned long convert(const std::string& s, const unsigned long&);
68  template<> unsigned long long convert(const std::string& s,
69  const unsigned long long&);
70 
71  // These specializations are used to convert text representations of durations
72  // (e.g. "10s") into their corresponding durations (e.g. std::chrono::seconds).
73  // Note that while these will convert the duration types, for example,
74  // seconds oneMinute = convert("1m");
75  // is perfectly valid and will be equivalent to 60s, they will throw an
76  // std::overflow_error if the resulting value cannot be represented by the desired
77  // type.
78  template<> std::chrono::hours convert(const std::string& s, const std::chrono::hours&);
79  template<> std::chrono::minutes convert(const std::string& s, const std::chrono::minutes&);
80  template<> std::chrono::seconds convert(const std::string& s, const std::chrono::seconds&);
81  template<> std::chrono::milliseconds convert(const std::string& s, const std::chrono::milliseconds&);
82  template<> std::chrono::microseconds convert(const std::string& s, const std::chrono::microseconds&);
83  template<> std::chrono::nanoseconds convert(const std::string& s, const std::chrono::nanoseconds&);
84 
85  // These specializations are used to convert text representations of time, in
86  // ISO8601 format, into time_point values. This covers the "standard" time_point
87  // definitions. If you have your own you will need to provide your own overrides.
88  template<>
89  std::chrono::time_point<std::chrono::system_clock, std::chrono::hours>
90  convert(const std::string& s, const std::chrono::time_point<std::chrono::system_clock, std::chrono::hours>&);
91 
92  template<>
93  std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>
94  convert(const std::string& s, const std::chrono::time_point<std::chrono::system_clock, std::chrono::minutes>&);
95 
96  template<>
97  std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>
98  convert(const std::string& s, const std::chrono::time_point<std::chrono::system_clock, std::chrono::seconds>&);
99 
100  template<>
101  std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>
102  convert(const std::string& s, const std::chrono::time_point<std::chrono::system_clock, std::chrono::milliseconds>&);
103 
104  template<>
105  std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds>
106  convert(const std::string& s, const std::chrono::time_point<std::chrono::system_clock, std::chrono::microseconds>&);
107 
108  template<>
109  std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>
110  convert(const std::string& s, const std::chrono::time_point<std::chrono::system_clock, std::chrono::nanoseconds>&);
111 
112 
113  template<>
114  std::chrono::time_point<std::chrono::steady_clock, std::chrono::hours>
115  convert(const std::string& s, const std::chrono::time_point<std::chrono::steady_clock, std::chrono::hours>&);
116 
117  template<>
118  std::chrono::time_point<std::chrono::steady_clock, std::chrono::minutes>
119  convert(const std::string& s, const std::chrono::time_point<std::chrono::steady_clock, std::chrono::minutes>&);
120 
121  template<>
122  std::chrono::time_point<std::chrono::steady_clock, std::chrono::seconds>
123  convert(const std::string& s, const std::chrono::time_point<std::chrono::steady_clock, std::chrono::seconds>&);
124 
125  template<>
126  std::chrono::time_point<std::chrono::steady_clock, std::chrono::milliseconds>
127  convert(const std::string& s, const std::chrono::time_point<std::chrono::steady_clock, std::chrono::milliseconds>&);
128 
129  template<>
130  std::chrono::time_point<std::chrono::steady_clock, std::chrono::microseconds>
131  convert(const std::string& s, const std::chrono::time_point<std::chrono::steady_clock, std::chrono::microseconds>&);
132 
133  template<>
134  std::chrono::time_point<std::chrono::steady_clock, std::chrono::nanoseconds>
135  convert(const std::string& s, const std::chrono::time_point<std::chrono::steady_clock, std::chrono::nanoseconds>&);
136 }}}
137 
138 #endif
Run Time Type Information.
T convert(const std::string &s, const T &=T())
Definition: convert.hpp:37