bool try_stou(const pal::string_t& str, unsigned* num) { if (str.empty()) { return false; } if (str.find_first_not_of(_X("0123456789")) != pal::string_t::npos) { return false; } *num = (unsigned) std::stoul(str); return true; }
size_t index_of_non_numeric(const pal::string_t& str, unsigned i) { return str.find_first_not_of(_X("0123456789"), i); }
bool parse_internal(const pal::string_t& ver, fx_ver_t* fx_ver, bool parse_only_production) { size_t maj_start = 0; size_t maj_sep = ver.find(_X('.')); if (maj_sep == pal::string_t::npos) { return false; } unsigned major = 0; if (!try_stou(ver.substr(maj_start, maj_sep), &major)) { return false; } size_t min_start = maj_sep + 1; size_t min_sep = ver.find(_X('.'), min_start); if (min_sep == pal::string_t::npos) { return false; } unsigned minor = 0; if (!try_stou(ver.substr(min_start, min_sep - min_start), &minor)) { return false; } unsigned patch = 0; size_t pat_start = min_sep + 1; size_t pat_sep = ver.find_first_not_of(_X("0123456789"), pat_start); if (pat_sep == pal::string_t::npos) { if (!try_stou(ver.substr(pat_start), &patch)) { return false; } *fx_ver = fx_ver_t(major, minor, patch); return true; } if (parse_only_production) { // This is a prerelease or has build suffix. return false; } if (!try_stou(ver.substr(pat_start, pat_sep - pat_start), &patch)) { return false; } size_t pre_start = pat_sep; size_t pre_sep = ver.find(_X('+'), pre_start); if (pre_sep == pal::string_t::npos) { *fx_ver = fx_ver_t(major, minor, patch, ver.substr(pre_start)); return true; } else { size_t build_start = pre_sep + 1; *fx_ver = fx_ver_t(major, minor, patch, ver.substr(pre_start, pre_sep - pre_start), ver.substr(build_start)); return true; } }