Skip to content

Commit 22d87ec

Browse files
authored
Merge 3bc3c22 into 6d74c06
2 parents 6d74c06 + 3bc3c22 commit 22d87ec

File tree

2 files changed

+98
-4
lines changed

2 files changed

+98
-4
lines changed

src/string_util.h

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,100 @@ inline std::string StrCat(Args&&... args) {
3232
return ss.str();
3333
}
3434

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+
35129
void ReplaceAll(std::string* str, const std::string& from,
36130
const std::string& to);
37131

src/sysinfo.cc

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ int CountSetBitsInCPUMap(std::string Val) {
225225
auto CountBits = [](std::string Part) {
226226
using CPUMask = std::bitset<sizeof(std::uintptr_t) * CHAR_BIT>;
227227
Part = "0x" + Part;
228-
CPUMask Mask(std::stoul(Part, nullptr, 16));
228+
CPUMask Mask(benchmark::stoul(Part, nullptr, 16));
229229
return static_cast<int>(Mask.count());
230230
};
231231
size_t Pos;
@@ -408,7 +408,7 @@ int GetNumCPUs() {
408408
if (ln.size() >= Key.size() && ln.compare(0, Key.size(), Key) == 0) {
409409
NumCPUs++;
410410
if (!value.empty()) {
411-
int CurID = std::stoi(value);
411+
int CurID = benchmark::stoi(value);
412412
MaxID = std::max(CurID, MaxID);
413413
}
414414
}
@@ -481,12 +481,12 @@ double GetCPUCyclesPerSecond() {
481481
// which would cause infinite looping in WallTime_Init.
482482
if (startsWithKey(ln, "cpu MHz")) {
483483
if (!value.empty()) {
484-
double cycles_per_second = std::stod(value) * 1000000.0;
484+
double cycles_per_second = benchmark::stod(value) * 1000000.0;
485485
if (cycles_per_second > 0) return cycles_per_second;
486486
}
487487
} else if (startsWithKey(ln, "bogomips")) {
488488
if (!value.empty()) {
489-
bogo_clock = std::stod(value) * 1000000.0;
489+
bogo_clock = benchmark::stod(value) * 1000000.0;
490490
if (bogo_clock < 0.0) bogo_clock = error_value;
491491
}
492492
}

0 commit comments

Comments
 (0)