@@ -32,6 +32,100 @@ inline std::string StrCat(Args&&... args) {
32
32
return ss.str ();
33
33
}
34
34
35
+ #if defined(__ANDROID__) && defined(__GLIBCXX__)
36
+ /*
37
+ * GNU STL in Android NDK lacks support for some C++11 functions, including
38
+ * stoul, stoi, stod. We reimplement them here using C functions strtoul,
39
+ * strtol, strtod. Note that reimplemented functions are in benchmark::
40
+ * namespace, not std:: namespace.
41
+ */
42
+ inline unsigned long stoul (const std::string& str, size_t * pos = nullptr ,
43
+ int base = 10 ) {
44
+ /* Record previous errno */
45
+ const int oldErrno = errno;
46
+ errno = 0 ;
47
+
48
+ const char * strStart = str.c_str ();
49
+ char * strEnd = const_cast <char *>(strStart);
50
+ const unsigned long result = strtoul (strStart, &strEnd, base);
51
+
52
+ const int strtoulErrno = errno;
53
+ /* Restore previous errno */
54
+ errno = oldErrno;
55
+
56
+ /* Check for errors and return */
57
+ if (strtoulErrno == ERANGE) {
58
+ throw std::out_of_range (
59
+ " stoul failed: " + str + " is outside of range of unsigned long" );
60
+ } else if (strEnd == strStart || strtoulErrno != 0 ) {
61
+ throw std::invalid_argument (
62
+ " stoul failed: " + str + " is not an integer" );
63
+ }
64
+ if (pos != nullptr ) {
65
+ *pos = static_cast <size_t >(strEnd - strStart);
66
+ }
67
+ return result;
68
+ }
69
+
70
+ inline int stoi (const std::string& str, size_t * pos = nullptr , int base = 10 ) {
71
+ /* Record previous errno */
72
+ const int oldErrno = errno;
73
+ errno = 0 ;
74
+
75
+ const char * strStart = str.c_str ();
76
+ char * strEnd = const_cast <char *>(strStart);
77
+ const long result = strtol (strStart, &strEnd, base);
78
+
79
+ const int strtolErrno = errno;
80
+ /* Restore previous errno */
81
+ errno = oldErrno;
82
+
83
+ /* Check for errors and return */
84
+ if (strtolErrno == ERANGE || long (int (result)) != result) {
85
+ throw std::out_of_range (
86
+ " stoul failed: " + str + " is outside of range of int" );
87
+ } else if (strEnd == strStart || strtolErrno != 0 ) {
88
+ throw std::invalid_argument (
89
+ " stoul failed: " + str + " is not an integer" );
90
+ }
91
+ if (pos != nullptr ) {
92
+ *pos = static_cast <size_t >(strEnd - strStart);
93
+ }
94
+ return int (result);
95
+ }
96
+
97
+ inline double stod (const std::string& str, size_t * pos = nullptr ) {
98
+ /* Record previous errno */
99
+ const int oldErrno = errno;
100
+ errno = 0 ;
101
+
102
+ const char * strStart = str.c_str ();
103
+ char * strEnd = const_cast <char *>(strStart);
104
+ const double result = strtod (strStart, &strEnd);
105
+
106
+ /* Restore previous errno */
107
+ const int strtodErrno = errno;
108
+ errno = oldErrno;
109
+
110
+ /* Check for errors and return */
111
+ if (strtodErrno == ERANGE) {
112
+ throw std::out_of_range (
113
+ " stoul failed: " + str + " is outside of range of int" );
114
+ } else if (strEnd == strStart || strtodErrno != 0 ) {
115
+ throw std::invalid_argument (
116
+ " stoul failed: " + str + " is not an integer" );
117
+ }
118
+ if (pos != nullptr ) {
119
+ *pos = static_cast <size_t >(strEnd - strStart);
120
+ }
121
+ return int (result);
122
+ }
123
+ #else
124
+ using std::stoul;
125
+ using std::stoi;
126
+ using std::stod;
127
+ #endif
128
+
35
129
void ReplaceAll (std::string* str, const std::string& from,
36
130
const std::string& to);
37
131
0 commit comments