diff options
Diffstat (limited to 'build/utility.cxx')
-rw-r--r-- | build/utility.cxx | 78 |
1 files changed, 78 insertions, 0 deletions
diff --git a/build/utility.cxx b/build/utility.cxx index d394186..7ee679b 100644 --- a/build/utility.cxx +++ b/build/utility.cxx @@ -4,6 +4,8 @@ #include <build/utility> +#include <cstdlib> // strtol() + using namespace std; namespace build @@ -12,5 +14,81 @@ namespace build const path empty_path; const dir_path empty_dir_path; + unsigned int + to_version (const string& s) + { + // See tests/version. + // + + auto parse = [&s] (size_t& p, const char* m, long min = 0, long max = 99) + -> unsigned int + { + if (s[p] == '-' || s[p] == '+') // stoi() allows these. + throw invalid_argument (m); + + const char* b (s.c_str () + p); + char* e; + long r (strtol (b, &e, 10)); + + if (b == e || r < min || r > max) + throw invalid_argument (m); + + p = e - s.c_str (); + return static_cast<unsigned int> (r); + }; + + auto bail = [] (const char* m) {throw invalid_argument (m);}; + + unsigned int ma, mi, bf, ab; + + size_t p (0), n (s.size ()); + ma = parse (p, "invalid major version"); + + if (p >= n || s[p] != '.') + bail ("'.' expected after major version"); + + mi = parse (++p, "invalid minor version"); + + if (p >= n || s[p] != '.') + bail ("'.' expected after minor version"); + + bf = parse (++p, "invalid bugfix version"); + + if (p < n) + { + if (s[p] != '-') + bail ("'-' expected after bugfix version"); + + char k (s[++p]); + + if (k != 'a' && k != 'b') + bail ("'a' or 'b' expected in release component"); + + ab = parse (++p, "invalid release component", 1, 49); + + if (p != n) + bail ("junk after release component"); + + if (k == 'b') + ab += 50; + } + + // AABBCCDD + unsigned int r (ma * 1000000U + + mi * 10000U + + bf * 100U); + + if (ab != 0) + { + if (r == 0) + bail ("0.0.0 version with release component"); + + r -= 100; + r += ab; + } + + return r; + } + bool exception_unwinding_dtor = false; } |