Skip to content

Commit bd75d42

Browse files
committed
Fix missing to_string errors.
Some C++ runtimes do not implement std::to_string, even in C++11 mode. Hence this avoids using those and instead we implement a simlple integer to_string equivalent. Which allows us to also avoid locale and base considerations.
1 parent 70ce57f commit bd75d42

File tree

2 files changed

+40
-6
lines changed

2 files changed

+40
-6
lines changed

cpp/include/versioned/versioned.hpp

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,21 @@ std::size_t hash_combine(std::size_t seed, N... an)
7676
return result;
7777
}
7878

79+
// Backfill to_string as it's missing on some runtimes.
80+
std::string to_string_10(std::size_t value)
81+
{
82+
std::string result;
83+
result.reserve(30);
84+
do
85+
{
86+
result += '0' + (value % 10);
87+
value /= 10;
88+
}
89+
while (value > 0);
90+
std::reverse(result.begin(), result.end());
91+
return result;
92+
}
93+
7994
} // namespace detail
8095

8196
struct from_chars_result
@@ -122,14 +137,16 @@ class version_core
122137
element_t & at(std::size_t i)
123138
{
124139
if (i >= element_c)
125-
throw std::out_of_range("No such component: " + std::to_string(i));
140+
throw std::out_of_range(
141+
"No such component: " + detail::to_string_10(i));
126142
return number[i];
127143
}
128144

129145
const element_t & at(std::size_t i) const
130146
{
131147
if (i >= element_c)
132-
throw std::out_of_range("No such component: " + std::to_string(i));
148+
throw std::out_of_range(
149+
"No such component: " + detail::to_string_10(i));
133150
return number[i];
134151
}
135152

@@ -173,7 +190,7 @@ from_chars_result from_chars(
173190
for (std::size_t i = 0; i < version_core<N, C>::element_c; ++i)
174191
{
175192
result.ptr = detail::from_chars_10(result.ptr, last, number[i]);
176-
if (*result.ptr != '.') break;
193+
if (result.ptr == last || *result.ptr != '.') break;
177194
result.ptr += 1;
178195
}
179196

@@ -191,9 +208,9 @@ std::string to_string(const version_core<N, C> & value)
191208
{
192209
std::size_t n = i - 1;
193210
if (n == 0)
194-
result = std::to_string(value.number[n]) + result;
211+
result = detail::to_string_10(value.number[n]) + result;
195212
else if (value.number[n] > 0)
196-
result = "." + std::to_string(value.number[n]) + result;
213+
result = "." + detail::to_string_10(value.number[n]) + result;
197214
}
198215
return result;
199216
}
@@ -283,7 +300,8 @@ class version_tag
283300
range_element_t range_at(std::size_t i) const
284301
{
285302
if (i >= parts_.size())
286-
throw std::out_of_range("No such component: " + std::to_string(i));
303+
throw std::out_of_range(
304+
"No such component: " + detail::to_string_10(i));
287305
return std::make_tuple(info_.c_str() + (i == 0 ? 0 : parts_[i - 1] + 1),
288306
info_.c_str() + parts_[i]);
289307
}

cpp/test/detail_run_test.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,5 +80,21 @@ int main()
8080
all("versioned::detail::from_chars_10",
8181
&versioned::detail::from_chars_10<int>);
8282
}
83+
{
84+
const std::size_t numbers[] = {
85+
0,
86+
1,
87+
2,
88+
9,
89+
99,
90+
999,
91+
1234567890,
92+
};
93+
for (auto n : numbers)
94+
{
95+
BOOST_TEST_EQ(
96+
std::to_string(n), versioned::detail::to_string_10(n));
97+
}
98+
}
8399
return boost::report_errors();
84100
}

0 commit comments

Comments
 (0)