1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215
|
/*
* Copyright (C) Volition, Inc. 1999. All rights reserved.
*
* All source code herein is the property of Volition, Inc. You may not sell
* or otherwise commercially exploit the source or things you created based on the
* source.
*
*/
#include "globalincs/version.h"
#include "globalincs/pstypes.h"
#include "graphics/2d.h"
#include "parse/parselo.h"
namespace gameversion {
bool check_at_least(const version& v) {
return get_executable_version() >= v;
}
SCP_string format_version(const version& v, bool exclude_build) {
SCP_stringstream ss;
ss << v.major << "." << v.minor;
if (!exclude_build) {
ss << "." << v.build;
if (v.revision != 0) {
ss << "." << v.revision;
}
}
return ss.str();
}
version parse_version() {
version v;
required_string("+Major:");
stuff_int(&v.major);
required_string("+Minor:");
stuff_int(&v.minor);
required_string("+Build:");
stuff_int(&v.build);
if (optional_string("+Revision:")) {
stuff_int(&v.revision);
}
return v;
}
version parse_version_inline() {
SCP_string input;
stuff_string(input, F_RAW);
return version(std::move(input), 0);
}
version get_executable_version() {
version v;
v.major = FS_VERSION_MAJOR;
v.minor = FS_VERSION_MINOR;
v.build = FS_VERSION_BUILD;
v.revision = FS_VERSION_REVIS;
return v;
}
version::version(int major_in, int minor_in, int build_in, int revision_in) :
major(major_in), minor(minor_in), build(build_in), revision(revision_in) {
}
version::version(const SCP_string& semver, int missing) : major(missing), minor(missing), build(missing), revision(missing) {
int i = 0;
auto str = semver;
int has_fields = 0;
while (i <= 4) {
size_t pos = str.find_first_of('.');
SCP_string ver;
if (pos != SCP_string::npos) {
ver = str.substr(0, pos);
str.erase(0, pos + 1);
}
else {
ver = str;
str.clear();
}
if (!ver.empty() && std::find_if(ver.begin(), ver.end(), [](char c) { return !std::isdigit(c, SCP_default_locale); }) == ver.end()) {
switch (has_fields) {
case 0:
major = std::stoi(ver.c_str());
++has_fields;
break;
case 1:
minor = std::stoi(ver.c_str());
++has_fields;
break;
case 2:
build = std::stoi(ver.c_str());
++has_fields;
break;
case 3:
revision = std::stoi(ver.c_str());
++has_fields;
break;
default:
UNREACHABLE("Version parsing broken, get a coder!");
break;
}
}
else
break; //Break out of the loop if the first string is not a digit.
i++;
}
}
bool version::isValid() const { return major != 0 || minor != 0 || build != 0 || revision != 0; }
bool version::operator<(const version& v) const {
if (major < v.major) {
return true;
}
if (major > v.major) {
// Major is greater than the given version => the rest doesn't matter
return false;
}
// major is now equal to our major version
if (minor < v.minor) {
return true;
}
if (minor > v.minor) {
// Minor is greater than the given version => the rest doesn't matter
return false;
}
// minor is now equal to our minor version
if (build < v.build) {
return true;
}
if (build > v.build) {
// build is greater than the given version => the rest doesn't matter
return false;
}
// build is now equal to our build version
if (revision == 0 || v.revision == 0) {
// Special case, if there is no revision info, then the versions are equal which means they are not less than each other
return false;
}
if (revision < v.revision) {
return true;
}
if (revision > v.revision) {
// build is greater than the given version => the rest doesn't matter
return false;
}
// revision is now equal to our revision version
return false;
}
bool version::operator==(const version& other) const {
if (major == other.major && minor == other.minor && build == other.build) {
if (revision == 0 || other.revision == 0) {
// Zero revisions always means that these are equal
return true;
}
return revision == other.revision;
}
return false;
}
bool version::operator>(const version& other) const {
return other < *this;
}
bool version::operator<=(const version& other) const {
return !(other < *this);
}
bool version::operator>=(const version& other) const {
return !(*this < other);
}
bool version::operator!=(const version& other) const {
return !(*this == other);
}
SCP_string get_version_string()
{
SCP_string str;
sprintf(str, "FreeSpace 2 Open v%s", FS_VERSION_FULL);
#ifndef NDEBUG
str += " Debug";
#endif
// Lets get some more info in here
switch (gr_screen.mode) {
case GR_OPENGL:
str += " OpenGL";
break;
case GR_VULKAN:
str += " Vulkan";
break;
}
return str;
}
}
|