Apache Mesos
numify.hpp
Go to the documentation of this file.
1 // Licensed under the Apache License, Version 2.0 (the "License");
2 // you may not use this file except in compliance with the License.
3 // You may obtain a copy of the License at
4 //
5 // http://www.apache.org/licenses/LICENSE-2.0
6 //
7 // Unless required by applicable law or agreed to in writing, software
8 // distributed under the License is distributed on an "AS IS" BASIS,
9 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 // See the License for the specific language governing permissions and
11 // limitations under the License.
12 
13 #ifndef __STOUT_NUMIFY_HPP__
14 #define __STOUT_NUMIFY_HPP__
15 
16 #include <sstream>
17 #include <string>
18 
19 #include <boost/lexical_cast.hpp>
20 
21 #include "error.hpp"
22 #include "none.hpp"
23 #include "option.hpp"
24 #include "result.hpp"
25 #include "strings.hpp"
26 #include "try.hpp"
27 
28 template <typename T>
29 Try<T> numify(const std::string& s)
30 {
31  try {
32  return boost::lexical_cast<T>(s);
33  } catch (const boost::bad_lexical_cast&) {
34  // Unfortunately boost::lexical_cast cannot cast a hexadecimal
35  // number even with a "0x" prefix, we have to workaround this
36  // issue here. We also process negative hexadecimal number "-0x"
37  // here to keep it consistent with non-hexadecimal numbers.
38  if (strings::startsWith(s, "0x") || strings::startsWith(s, "0X") ||
39  strings::startsWith(s, "-0x") || strings::startsWith(s, "-0X")) {
40  // NOTE: Hexadecimal floating-point constants (e.g., 0x1p-5,
41  // 0x10.0), are allowed in C99, but cannot be used as floating
42  // point literals in standard C++. Some C++ compilers might
43  // accept them as an extension; for consistency, we always
44  // disallow them. See:
45  // https://gcc.gnu.org/onlinedocs/gcc/Hex-Floats.html
46  if (!strings::contains(s, ".") && !strings::contains(s, "p")) {
47  T result;
48  std::stringstream ss;
49  // Process negative hexadecimal numbers.
50  if (strings::startsWith(s, "-")) {
51  ss << std::hex << s.substr(1);
52  ss >> result;
53  // Note: When numify is instantiated with unsigned scalars
54  // the expected behaviour is as follow:
55  // numify<T>("-1") == std::numeric_limits<T>::max();
56  // Disabled unary negation warning for all types.
57 #ifdef __WINDOWS__
58  #pragma warning(disable:4146)
59 #endif
60  result = -result;
61 #ifdef __WINDOWS__
62  #pragma warning(default:4146)
63 #endif
64  } else {
65  ss << std::hex << s;
66  ss >> result;
67  }
68  // Make sure we really hit the end of the string.
69  if (!ss.fail() && ss.eof()) {
70  return result;
71  }
72  }
73  }
74 
75  return Error("Failed to convert '" + s + "' to number");
76  }
77 }
78 
79 
80 template <typename T>
81 Try<T> numify(const char* s)
82 {
83  return numify<T>(std::string(s));
84 }
85 
86 
87 template <typename T>
89 {
90  if (s.isSome()) {
91  Try<T> t = numify<T>(s.get());
92  if (t.isSome()) {
93  return t.get();
94  } else if (t.isError()) {
95  return Error(t.error());
96  }
97  }
98 
99  return None();
100 }
101 
102 #endif // __STOUT_NUMIFY_HPP__
Definition: errorbase.hpp:35
Definition: try.hpp:34
Definition: result.hpp:40
bool isSome() const
Definition: option.hpp:115
Try< T > numify(const std::string &s)
Definition: numify.hpp:29
bool contains(const std::string &s, const std::string &substr)
Definition: strings.hpp:406
bool isSome() const
Definition: try.hpp:70
const T & get() const &
Definition: option.hpp:118
static Try error(const E &e)
Definition: try.hpp:42
Definition: none.hpp:27
bool isError() const
Definition: try.hpp:71
bool startsWith(const std::string &s, const std::string &prefix)
Definition: strings.hpp:380
const T & get() const
Definition: try.hpp:73