The Battle for Wesnoth  1.13.4+dev
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Modules Pages
version.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2008 - 2016 by Ignacio R. Morelle <[email protected]>
3  Part of the Battle for Wesnoth Project http://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #include "version.hpp"
17 #include "util.hpp"
18 
19 #include <cassert>
20 #include <functional>
21 
23  : nums_(3,0), special_(""), special_separator_('\0')
24 {
25 }
26 
27 version_info::version_info(unsigned int major, unsigned int minor, unsigned int revision_level,
28  char special_separator, const std::string& special)
29  : nums_(3,0), special_(special), special_separator_(special_separator)
30 {
31  nums_[0] = major;
32  nums_[1] = minor;
33  nums_[2] = revision_level;
34 }
35 
37  : nums_(3,0)
38  , special_("")
39  , special_separator_('\0')
40 {
41  std::string v = str;
42  utils::strip(v);
43 
44  if(v.empty())
45  return;
46 
47  //
48  // The breakpoint is where the "special" version component begins.
49  // For 1.1.2a it would at the index of the char 'a'. For 1.1.4+dev it is at '+'.
50  //
51  // For 1.5.2 it is at npos.
52  //
53  const std::string::size_type breakpoint_pos = v.find_first_not_of(".0123456789");
54  std::string left_side;
55  if(breakpoint_pos != std::string::npos) {
56  const std::string right_side = v.substr(breakpoint_pos);
57  assert(right_side.empty() == false);
58 
59  if((right_side[0] >= 'A' && right_side[0] <= 'Z') || (right_side[0] >= 'a' && right_side[0] <= 'z')) {
60  special_separator_ = '\0';
61  special_ = right_side;
62  }
63  else {
64  special_separator_ = right_side[0];
65  if(right_side.size() > 1) {
66  special_ = right_side.substr(1);
67  }
68  }
69 
70  left_side = v.substr(0, breakpoint_pos);
71  }
72  else {
73  left_side = v;
74  }
75 
76  const std::vector<std::string> components = utils::split(left_side, '.');
77  const size_t s = components.size();
78  if(s == 0) {
79  return;
80  }
81  else if(s > 3) {
82  nums_.resize(s, 0);
83  }
84 
85  for(size_t i = 0; (i < s); ++i) {
86  nums_[i] = lexical_cast_default<unsigned int>(components[i]);
87  }
88 }
89 
91 {
92  const size_t s = nums_.size();
93 
94  std::ostringstream o;
95  for(size_t k = 0; k < s; ++k) {
96  o << nums_[k];
97 
98  if(s != 1+k) {
99  o << '.';
100  }
101  }
102 
103  if(! special_.empty()) {
104  if(special_separator_ != '\0') {
105  o << special_separator_;
106  }
107 
108  o << special_;
109  }
110 
111  return o.str();
112 }
113 
114 void version_info::set_major_version(unsigned int v) {
115  nums_[0] = v;
116 }
117 
118 void version_info::set_minor_version(unsigned int v) {
119  nums_[1] = v;
120 }
121 
123  nums_[2] = v;
124 }
125 
126 unsigned int version_info::major_version() const {
127  return nums_[0];
128 }
129 
130 unsigned int version_info::minor_version() const {
131  return nums_[1];
132 }
133 
134 unsigned int version_info::revision_level() const {
135  return nums_[2];
136 }
137 
139  return nums_.size() <= 3;
140 }
141 
142 namespace {
143  enum COMP_TYPE {
144  EQUAL,
145  NOT_EQUAL,
146  LT, GT
147  };
148 
149  /*
150  x > y
151  x0.x1.x2.x3.[...].xN > y0.y1.y2.y3.[...].yN iff
152 
153  x0 > y0 || (x0 == y0 && (x1 > y1 || (x1 == y1 && (x2 > y2 || (x2 >= y2 ||
154 
155  */
156  template<typename _Toperator, typename _Tfallback_operator>
157  bool recursive_order_operation(const std::vector<unsigned int>& l, const std::vector<unsigned int>& r, size_t k)
158  {
159  if(k >= l.size() || k >= r.size()) {
160  return false;
161  }
162 
163  unsigned int const& lvalue = l[k];
164  unsigned int const& rvalue = r[k];
165 
166  _Toperator o;
167  _Tfallback_operator fallback_o;
168 
169  bool ret = o(lvalue, rvalue);
170  if((!ret) && fallback_o(lvalue, rvalue)) {
171  ret = recursive_order_operation<_Toperator, _Tfallback_operator>(l,r,++k);
172  }
173  return ret;
174  }
175 
176 #ifdef _MSC_VER
177 #pragma warning (push)
178 #pragma warning (disable: 4706)
179 #endif
180  bool version_numbers_comparison_internal(const version_info& l, const version_info& r, COMP_TYPE o)
181  {
182  std::vector<unsigned int> lc = l.components();
183  std::vector<unsigned int> rc = r.components();
184 
185  const size_t lsize = lc.size();
186  const size_t rsize = rc.size();
187  const size_t csize = std::max(lsize, rsize);
188 
189  // make compatible, missing items default to zero
190  if(lsize < csize) lc.resize(csize, 0);
191  if(rsize < csize) rc.resize(csize, 0);
192 
193  bool result = true;
194 
195  const std::vector<unsigned int>& lcc = lc;
196  const std::vector<unsigned int>& rcc = rc;
197 
198  switch(o)
199  {
200  case EQUAL: case NOT_EQUAL: {
201  for(size_t i = 0; i < csize; ++i) {
202  unsigned int const& lvalue = lc[i];
203  unsigned int const& rvalue = rc[i];
204  if(o == NOT_EQUAL) {
205  if((result = (lvalue != rvalue))) {
206 #ifdef _MSC_VER
207 #pragma warning (pop)
208 #endif
209  return true;
210  }
211  continue;
212  } else {
213  result = result && lvalue == rvalue;
214  if(!result) {
215  break;
216  }
217  }
218  }
219  break;
220  }
221  case LT:
222  result = recursive_order_operation<std::less<unsigned int>, std::equal_to<unsigned int> >(lcc, rcc, 0);
223  break;
224  case GT:
225  result = recursive_order_operation<std::greater<unsigned int>, std::equal_to<unsigned int> >(lcc, rcc, 0);
226  break;
227  default:
228  assert(0 == 1);
229  break;
230  }
231  return result;
232  }
233 
234 } // end unnamed namespace
235 
236 bool operator==(const version_info& l, const version_info& r)
237 {
238  return version_numbers_comparison_internal(l, r, EQUAL) && l.special_version() == r.special_version();
239 }
240 
241 bool operator!=(const version_info& l, const version_info& r)
242 {
243  return version_numbers_comparison_internal(l, r, NOT_EQUAL) || l.special_version() != r.special_version();
244 }
245 
246 bool operator<(const version_info& l, const version_info& r)
247 {
248  return version_numbers_comparison_internal(l, r, LT) || (
249  version_numbers_comparison_internal(l, r, EQUAL) && (
250  (l.special_version().empty() && !r.special_version().empty()) ||
251  (l.special_version() < r.special_version())
252  )
253  );
254 }
255 
256 bool operator>(const version_info& l, const version_info& r)
257 {
258  return version_numbers_comparison_internal(l, r, GT) || (
259  version_numbers_comparison_internal(l, r, EQUAL) && (
260  (r.special_version().empty() && !l.special_version().empty()) ||
261  (l.special_version() > r.special_version())
262  )
263  );
264 }
265 
266 bool operator<=(const version_info& l, const version_info& r)
267 {
268  return l < r || l == r;
269 }
270 
271 bool operator>=(const version_info& l, const version_info& r)
272 {
273  return l > r || l == r;
274 }
275 
277 {
278  if(op_str == "==") {
279  return OP_EQUAL;
280  } else if(op_str == "!=") {
281  return OP_NOT_EQUAL;
282  } else if(op_str == "<") {
283  return OP_LESS;
284  } else if(op_str == "<=") {
285  return OP_LESS_OR_EQUAL;
286  } else if(op_str == ">") {
287  return OP_GREATER;
288  } else if(op_str == ">=") {
289  return OP_GREATER_OR_EQUAL;
290  }
291 
292  return OP_INVALID;
293 }
294 
296 {
297  switch(op) {
298  case OP_EQUAL:
299  return a == b;
300  case OP_NOT_EQUAL:
301  return a != b;
302  case OP_LESS:
303  return a < b;
304  case OP_LESS_OR_EQUAL:
305  return a <= b;
306  case OP_GREATER:
307  return a > b;
308  case OP_GREATER_OR_EQUAL:
309  return a >= b;
310  default:
311  ;
312  }
313 
314  return false;
315 }
std::string special_
Definition: version.hpp:178
bool is_canonical() const
Whether the version number is considered canonical for mainline Wesnoth.
Definition: version.cpp:138
VERSION_COMP_OP parse_version_op(const std::string &op_str)
Definition: version.cpp:276
bool operator>(const version_info &l, const version_info &r)
Greater-than operator for version_info.
Definition: version.cpp:256
void set_major_version(unsigned int)
Sets the major version number.
Definition: version.cpp:114
void set_revision_level(unsigned int)
Sets the revision level.
Definition: version.cpp:122
const std::vector< unsigned int > & components() const
Read-only access to all numeric components.
Definition: version.hpp:171
COMP_TYPE
Definition: version.cpp:143
char special_separator_
Definition: version.hpp:179
GLdouble l
Definition: glew.h:6966
std::string & strip(std::string &str)
Remove whitespace from the front and back of the string 'str'.
GLdouble GLdouble GLdouble b
Definition: glew.h:6966
GLuint64EXT * result
Definition: glew.h:10727
const GLdouble * v
Definition: glew.h:1359
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:7319
Templates and utility-routines for strings and numbers.
void set_minor_version(unsigned int)
Sets the minor version number.
Definition: version.cpp:118
GLenum GLenum GLuint components
Definition: glew.h:9242
std::string str() const
Serializes the version number into string form.
Definition: version.cpp:90
unsigned int revision_level() const
Retrieves the revision level (x3 in "x1.x2.x3").
Definition: version.cpp:134
VERSION_COMP_OP
Definition: version.hpp:195
bool operator>=(const version_info &l, const version_info &r)
Greater-than-or-equal operator for version_info.
Definition: version.cpp:271
unsigned int minor_version() const
Retrieves the minor version number (x2 in "x1.x2.x3").
Definition: version.cpp:130
bool operator<(const version_info &l, const version_info &r)
Less-than operator for version_info.
Definition: version.cpp:246
bool operator!=(const version_info &l, const version_info &r)
Inequality operator for version_info.
Definition: version.cpp:241
unsigned int major_version() const
Retrieves the major version number (x1 in "x1.x2.x3").
Definition: version.cpp:126
size_t i
Definition: function.cpp:1057
GLdouble GLdouble GLdouble r
Definition: glew.h:1374
Represents version numbers.
Definition: version.hpp:44
std::vector< std::string > split(std::string const &val, const char c, const int flags)
Splits a (comma-)separated string into a vector of pieces.
bool do_version_check(const version_info &a, VERSION_COMP_OP op, const version_info &b)
Definition: version.cpp:295
version_info()
Default constructor.
Definition: version.cpp:22
const std::string & special_version() const
Retrieves the special version suffix (e.g.
Definition: version.hpp:112
bool operator==(const version_info &l, const version_info &r)
Equality operator for version_info.
Definition: version.cpp:236
GLdouble s
Definition: glew.h:1358
Interfaces for manipulating version numbers of engine, add-ons, etc.
std::vector< unsigned int > nums_
Definition: version.hpp:177
GLsizei const GLcharARB ** string
Definition: glew.h:4503
bool operator<=(const version_info &l, const version_info &r)
Less-than-or-equal operator for version_info.
Definition: version.cpp:266