1 /*
2 	Actiona
3 	Copyright (C) 2005 Jonathan Mercier-Ganady
4 
5 	Actiona 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 3 of the License, or
8 	(at your option) any later version.
9 
10 	Actiona is distributed in the hope that it will be useful,
11 	but WITHOUT ANY WARRANTY; without even the implied warranty of
12 	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 	GNU General Public License for more details.
14 
15 	You should have received a copy of the GNU General Public License
16 	along with this program. If not, see <http://www.gnu.org/licenses/>.
17 
18 	Contact : jmgr@jmgr.info
19 */
20 
21 #include "version.h"
22 
23 #if (QT_VERSION < 0x050600)
24 #include <QRegExp>
25 #include <QStringList>
26 #include <QDataStream>
27 
28 namespace Tools
29 {
Version()30 	Version::Version()
31 		: d(new VersionData())
32 	{
33 	}
34 
Version(const QString & str)35 	Version::Version(const QString &str)
36 		: d(new VersionData())
37 	{
38 		setFromString(str);
39 	}
40 
Version(const Version & other)41 	Version::Version(const Version &other)
42 		: d(other.d)
43 	{
44 	}
45 
Version(int major,int minor,int micro,int nano)46 	Version::Version(int major, int minor, int micro, int nano)
47 		: d(new VersionData())
48 	{
49 		setMajor(major);
50 		setMinor(minor);
51 		setMicro(micro);
52 		setNano(nano);
53 
54 		setNumberCount(4);
55 	}
56 
Version(int major,int minor,int micro)57 	Version::Version(int major, int minor, int micro)
58 		: d(new VersionData())
59 	{
60 		setMajor(major);
61 		setMinor(minor);
62 		setMicro(micro);
63 
64 		setNumberCount(3);
65 	}
66 
Version(int major,int minor)67 	Version::Version(int major, int minor)
68 		: d(new VersionData())
69 	{
70 		setMajor(major);
71 		setMinor(minor);
72 
73 		setNumberCount(2);
74 	}
75 
Version(int major)76 	Version::Version(int major)
77 		: d(new VersionData())
78 	{
79 		setMajor(major);
80 
81 		setNumberCount(1);
82 	}
83 
toString() const84 	QString Version::toString() const
85 	{
86 		switch(numberCount())
87 		{
88 		case 1:
89 			return QString("%1").arg(d->major);
90 		case 2:
91 			return QString("%1.%2").arg(d->major).arg(d->minor);
92 		case 3:
93 			return QString("%1.%2.%3").arg(d->major).arg(d->minor).arg(d->micro);
94 		case 4:
95 			return QString("%1.%2.%3.%4").arg(d->major).arg(d->minor).arg(d->micro).arg(d->nano);
96 		default:
97 			return QString();
98 		}
99 	}
100 
setFromString(const QString & str)101 	bool Version::setFromString(const QString &str)
102 	{
103 		int newNumberCount = str.count('.') + 1;
104 		if(newNumberCount < 1 || newNumberCount > 4)
105 		{
106 			d->major = d->minor = d->micro = d->nano = 0;
107 			return false;
108 		}
109 
110 		setNumberCount(newNumberCount);
111 
112 		QRegExp regExp(regExpForNumberCount(newNumberCount));
113 
114 		if(!regExp.exactMatch(str))
115 		{
116 			d->major = d->minor = d->micro = d->nano = 0;
117 			return false;
118 		}
119 
120 		const QStringList versionNumbers = regExp.capturedTexts();
121 
122 		if((versionNumbers.count() - 1) != newNumberCount)
123 		{
124 			d->major = d->minor = d->micro = d->nano = 0;
125 			return false;
126 		}
127 
128 		d->major = versionNumbers.at(1).toInt();
129 		if(newNumberCount >= 2)
130 			d->minor = versionNumbers.at(2).toInt();
131 		if(newNumberCount >= 3)
132 			d->micro = versionNumbers.at(3).toInt();
133 		if(newNumberCount >= 4)
134 			d->nano = versionNumbers.at(4).toInt();
135 
136 		return true;
137 	}
138 
swap(Version & other)139 	void Version::swap(Version &other)
140 	{
141 		d.swap(other.d);
142 	}
143 
isValidVersion(const QString & str)144 	bool Version::isValidVersion(const QString &str)
145 	{
146 		int newNumberCount = str.count('.') + 1;
147 		if(newNumberCount < 1 || newNumberCount > 4)
148 			return false;
149 
150 		QRegExp regExp(regExpForNumberCount(newNumberCount));
151 
152 		return regExp.exactMatch(str);
153 	}
154 
operator =(Version other)155 	Version &Version::operator= (Version other)
156 	{
157 		swap(other);
158 
159 		return *this;
160 	}
161 
operator ==(const Version & other) const162 	bool Version::operator== (const Version &other) const
163 	{
164 		if(d->numberCount != other.d->numberCount)
165 			return false;
166 
167 		switch(numberCount())
168 		{
169 		case 1:
170 			return (d->major == other.d->major);
171 		case 2:
172 			return (d->major == other.d->major && d->minor == other.d->minor);
173 		case 3:
174 			return (d->major == other.d->major && d->minor == other.d->minor && d->micro == other.d->micro);
175 		case 4:
176 			return (d->major == other.d->major && d->minor == other.d->minor && d->micro == other.d->micro && d->nano == other.d->nano);
177 		default:
178 			return false;
179 		}
180 	}
181 
operator !=(const Version & other) const182 	bool Version::operator!= (const Version &other) const
183 	{
184 		return !((*this) == other);
185 	}
186 
operator <(const Version & other) const187 	bool Version::operator< (const Version &other) const
188 	{
189 		if(d->numberCount != other.d->numberCount)
190 			return false;
191 
192 		switch(numberCount())
193 		{
194 		case 1:
195 			if(d->major < other.d->major)
196 				return true;
197 
198 			return false;
199 		case 2:
200 			if(d->major < other.d->major)
201 				return true;
202 			if(d->major > other.d->major)
203 				return false;
204 			if(d->minor < other.d->minor)
205 				return true;
206 			if(d->minor > other.d->minor)
207 				return false;
208 
209 			return false;
210 		case 3:
211 			if(d->major < other.d->major)
212 				return true;
213 			if(d->major > other.d->major)
214 				return false;
215 			if(d->minor < other.d->minor)
216 				return true;
217 			if(d->minor > other.d->minor)
218 				return false;
219 			if(d->micro < other.d->micro)
220 				return true;
221 			if(d->micro > other.d->micro)
222 				return false;
223 
224 			return false;
225 		case 4:
226 			if(d->major < other.d->major)
227 				return true;
228 			if(d->major > other.d->major)
229 				return false;
230 			if(d->minor < other.d->minor)
231 				return true;
232 			if(d->minor > other.d->minor)
233 				return false;
234 			if(d->micro < other.d->micro)
235 				return true;
236 			if(d->micro > other.d->micro)
237 				return false;
238 			if(d->nano < other.d->nano)
239 				return true;
240 			if(d->nano > other.d->nano)
241 				return false;
242 
243 			return false;
244 		default:
245 			return false;
246 		}
247 	}
248 
operator >(const Version & other) const249 	bool Version::operator> (const Version &other) const
250 	{
251 		if(d->numberCount != other.d->numberCount)
252 			return false;
253 
254 		switch(numberCount())
255 		{
256 		case 1:
257 			if(d->major > other.d->major)
258 				return true;
259 
260 			return false;
261 		case 2:
262 			if(d->major > other.d->major)
263 				return true;
264 			if(d->major < other.d->major)
265 				return false;
266 			if(d->minor > other.d->minor)
267 				return true;
268 			if(d->minor < other.d->minor)
269 				return false;
270 
271 			return false;
272 		case 3:
273 			if(d->major > other.d->major)
274 				return true;
275 			if(d->major < other.d->major)
276 				return false;
277 			if(d->minor > other.d->minor)
278 				return true;
279 			if(d->minor < other.d->minor)
280 				return false;
281 			if(d->micro > other.d->micro)
282 				return true;
283 			if(d->micro < other.d->micro)
284 				return false;
285 
286 			return false;
287 		case 4:
288 			if(d->major > other.d->major)
289 				return true;
290 			if(d->major < other.d->major)
291 				return false;
292 			if(d->minor > other.d->minor)
293 				return true;
294 			if(d->minor < other.d->minor)
295 				return false;
296 			if(d->micro > other.d->micro)
297 				return true;
298 			if(d->micro < other.d->micro)
299 				return false;
300 			if(d->nano > other.d->nano)
301 				return true;
302 			if(d->nano < other.d->nano)
303 				return false;
304 
305 			return false;
306 		default:
307 			return false;
308 		}
309 	}
310 
operator <=(const Version & other) const311 	bool Version::operator<= (const Version &other) const
312 	{
313 		return ((*this) < other || (*this) == other);
314 	}
315 
operator >=(const Version & other) const316 	bool Version::operator>= (const Version &other) const
317 	{
318 		return ((*this) > other || (*this) == other);
319 	}
320 
regExpForNumberCount(int numberCount)321 	QString Version::regExpForNumberCount(int numberCount)
322 	{
323 		switch(numberCount)
324 		{
325 		case 1:
326 			return "^([0-9]+)$";
327 		case 2:
328 			return "^([0-9]+)\\.([0-9]+)$";
329 		case 3:
330 			return "^([0-9]+)\\.([0-9]+)\\.([0-9]+)$";
331 		case 4:
332 			return "^([0-9]+)\\.([0-9]+)\\.([0-9]+)\\.([0-9]+)$";
333 		default:
334 			return QString();
335 		}
336 	}
337 }
338 
operator <<(QDataStream & s,const Tools::Version & version)339 QDataStream &operator<<(QDataStream &s, const Tools::Version &version)
340 {
341 	s << version.major();
342 	s << version.minor();
343 	s << version.micro();
344 	s << version.nano();
345 	s << version.numberCount();
346 
347 	return s;
348 }
349 
operator >>(QDataStream & s,Tools::Version & version)350 QDataStream &operator>>(QDataStream &s, Tools::Version &version)
351 {
352 	int major, minor, micro, nano, numberCount;
353 
354 	s >> major;
355 	s >> minor;
356 	s >> micro;
357 	s >> nano;
358 	s >> numberCount;
359 
360 	version.setMajor(major);
361 	version.setMinor(minor);
362 	version.setMicro(micro);
363 	version.setNano(nano);
364 	version.setNumberCount(numberCount);
365 
366 	return s;
367 }
368 
operator <<(QDebug & dbg,const Tools::Version & version)369 QDebug &operator<<(QDebug &dbg, const Tools::Version &version)
370 {
371 	dbg.nospace() << version.toString();
372 
373 	return dbg.maybeSpace();
374 }
375 #endif
376