Skip to content

Instantly share code, notes, and snippets.

@yuiAs
Last active March 9, 2016 11:34
Show Gist options
  • Select an option

  • Save yuiAs/20b986bb30cf372079b4 to your computer and use it in GitHub Desktop.

Select an option

Save yuiAs/20b986bb30cf372079b4 to your computer and use it in GitHub Desktop.
Expand number list with ranges
template <typename T>
std::deque<T> expand_ranges(const std::string& src, size_t limit)
{
std::deque<T> r;
// 現状の parseStringToでは結局分割した std::stringが必要なので先に splitでバラしておく
auto a = split(src, ',');
for (auto it = a.cbegin(); ((it != a.cend()) && (r.size() <= limit)); ++it) {
T v1;
if (parseStringTo<T>(v1, *it) == it->size()) {
auto w = std::lower_bound(r.cbegin(), r.cend(), v1);
if ((w == r.cend()) || (*w != v1)) {
r.insert(w, v1);
}
} else {
// NOTE: 次の文字を直接見るというのは怖いのでやらない
std::string::size_type p0 = 0;
while (p0 < it->size()) {
std::string::size_type p1 = it->find_first_of('-', p0);
// p0==p1は負数の '-'
if (p0 == p1) {
std::string::size_type p2 = p1 + 1;
std::string::size_type p3 = it->find_first_of('-', p2);
if (p3 == std::string::npos) {
// これは範囲指定がおかしい (終点指定がない)
std::cerr << "!not found range end: " << *it << std::endl;
break;
} else {
// lhs
if (parseStringTo<T>(v1, it->substr(p0, (p3 - p0))) != (p3 - p0)) {
// 文字列 -> 数値でなんらかのエラーが発生してるので継続しない
std::cerr << "!unknown: " << *it << std::endl;
break;
} else {
p0 = p3 + 1;
}
}
} else {
if (p1 == std::string::npos) {
// 最低でも +1して回すためないとは思うけど一応終端チェック
break;
} else {
// lhs
size_t length = p1 - p0;
if (parseStringTo<T>(v1, it->substr(p0, length)) != length) {
// 文字列 -> 数値でなんらかのエラーが発生してるので継続しない
std::cerr << "!unknown2: " << *it << std::endl;
break;
} else {
p0 = p1 + 1;
}
}
}
// rhs
if (p0 < it->size()) {
T v2;
size_t length = it->size() - p0 + 1;
if (parseStringTo<T>(v2, it->substr(p0)) != length) {
if (v2 < v1) {
std::swap(v1, v2);
}
for (auto i = v1; ((i <= v2) && (r.size() <= limit)); ++i) {
auto w = std::lower_bound(r.cbegin(), r.cend(), i);
if ((w == r.cend()) || (*w != i)) {
r.insert(w, i);
}
}
} else {
// 文字列 -> 数値でなんらかのエラーが発生してるので継続しない
std::cerr << "!unknown3: " << *it << std::endl;
}
} else {
// これは範囲指定がおかしい (終点指定がない)
std::cerr << "!not found range end: " << *it << std::endl;
}
break;
}
}
}
return r;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment