namespace Usm { public class Version { public int[] version_nums { get; set; } public int? release { get; set; } public Version.from_string(string ver) throws ManifestError { var ver_rel = ver.chomp().chug().split("+", 2); if(ver_rel.length == 2) { var release = 0; if(!int.try_parse(ver_rel[1], out release)) { throw new ManifestError.INVALID_VERSION("Could not parse release number"); } this.release = release; } if(ver_rel[0].length == 0) { if(this.release == null) { throw new ManifestError.INVALID_VERSION("Version string must have a version number or release number at minimum"); } return; } var version_strs = ver_rel[0].split("."); version_nums = new int[version_strs.length]; for(int i = 0; i < version_nums.length; i++) { var num = 0; if(!int.try_parse(version_strs[i], out num)) { throw new ManifestError.INVALID_VERSION(@"Could not parse version number part $i"); } version_nums[i] = num; } } public string to_string() { var str = ""; bool first = true; foreach (var num in version_nums) { if(first) { first = false; } else { str += "."; } str += num.to_string(); } if(release != null) { str += @"+$release"; } return str; } public bool equals(Version other) { var parts = int.min(other.version_nums.length, version_nums.length); for(int i = 0; i < parts; i++) { if(version_nums[i] != other.version_nums[i]) { return false; } } return release == other.release; } /** * Prefix-tolerant numeric equality ignoring `+release` suffixes: * 0.31 matches 0.31.0, and 0.31+2 matches 0.31. Resource-level * versions (soname tails, .pc `Version:` fields) never carry * packaging releases and upstreams disagree about component * counts, so this is the equality resource constraints use. */ public bool matches_numeric(Version other) { var mine = version_nums ?? new int[0]; var theirs = other.version_nums ?? new int[0]; var parts = int.min(theirs.length, mine.length); for(int i = 0; i < parts; i++) { if(mine[i] != theirs[i]) { return false; } } return true; } public bool greater_than(Version other) { var parts = int.min(other.version_nums.length, version_nums.length); for(int i = 0; i < parts; i++) { if(version_nums[i] > other.version_nums[i]) { return true; } if(version_nums[i] < other.version_nums[i]) { return false; } } // So far, equal if(release == null && other.release == null) { return false; } if(release == null && other.release != null) { return false; } if(release != null && other.release == null) { return true; } return release > other.release; } public bool less_than(Version other) { var parts = int.min(other.version_nums.length, version_nums.length); for(int i = 0; i < parts; i++) { if(version_nums[i] < other.version_nums[i]) { return true; } if(version_nums[i] > other.version_nums[i]) { return false; } } // So far, equal if(release == null && other.release == null) { return false; } if(release == null && other.release != null) { return true; } if(release != null && other.release == null) { return false; } return release < other.release; } public int compare(Version other) { if(less_than(other)) { return -1; } if(greater_than(other)) { return 1; } return 0; } } }