Skip to content

Instantly share code, notes, and snippets.

@Fiona-J-W
Created May 2, 2014 17:50
Show Gist options
  • Save Fiona-J-W/a5a6b5b064f3a8efb924 to your computer and use it in GitHub Desktop.
Save Fiona-J-W/a5a6b5b064f3a8efb924 to your computer and use it in GitHub Desktop.
char-range to integer
#include <array>
#include <cassert>
#include <chrono>
#include <iostream>
#include <limits>
#include <random>
#include <sstream>
#include <string>
#include <tuple>
#include <type_traits>
#include <vector>
template<typename CharIterator>
std::tuple<CharIterator, char> drop_spaces(CharIterator it, CharIterator end) {
char c;
while(it != end && std::isspace((c = *it))) {
++it;
}
return std::make_tuple(it, c);
}
template<typename Integer, typename CharIterator>
std::tuple<Integer, CharIterator, char> fast_str_to_integer(CharIterator it, const CharIterator end) {
//static_assert(std::is_arithmetic<Integer>::value, "fast_str_to<T> only works for integers");
char c;
std::tie(it, c) = drop_spaces(it, end);
bool is_negative = false;
if(std::is_signed<Integer>::value) { // this should be optimized away entirely
switch (c) {
case '-':
is_negative = true;
// fallthrough
case '+':
++it;
if (it == end) {
throw std::invalid_argument{"string contains no digits"};
}
c = *it;
break;
default:
break;
}
}
if(!isdigit(c)) {
throw std::invalid_argument{"string contains no digits"};
}
Integer val = 0;
while (true) {
assert(std::numeric_limits<Integer>::max() / 10 >= val);
val *= 10;
c -= '0';
assert(std::numeric_limits<Integer>::max() - c >= val);
val += c;
++it;
if(it == end) {
break;
}
c = *it;
if(!isdigit(c)) {
break;
}
}
if(is_negative) {
val = -val;
}
std::tie(it, c) = drop_spaces(it, end);
return std::make_tuple(val, it, c);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment