[Development] Adding support for version number comparisons

André Somers andre at familiesomers.nl
Wed May 14 15:10:07 CEST 2014

Keith Gardner schreef op 14-5-2014 14:28:
>     I think that makes sense, but it would be nice if it would be easy
>     for the user of the class to extend the version checking himself
>     for non-numerical sections of the version string. That could be
>     done in several ways I think, for instance with an API like this:
>     QVersion
>     {
>     ...
>     protected:
>         virtual bool isNonNumericalSectionLessThan(int section,
>     QStringRef sectionString) const;
>     ...
>     }
>     The default implementation would simply return false and thus not
>     try to do any sorting.
>     That or another method to accomplish the same makes it easy to use
>     the class for basic version numbers, while still be flexible
>     enough for users to handle their own systems for pre and
>     postfixes, right?
> Are you envisioning the overload to be passed as a parameter to the 
> compare function or have it be stored as a static variable so it only 
> needs to be set once?
Well, if you use a virtual, you'd simply subclass to handle the specific 
format for your project. I would not use a static variable with a custom 
compare function. What if an application has to handle more than one 
version format?
> As for prefixes, I have not come across a project that reports its 
> version with a prefix.  If we were to support prefixes, I would say 
> that there would have to be more restrictions on their format in order 
> to support converting from a QString to a QVersion.  The biggest 
> restriction I can think of is to not support numbers in the prefix 
> string to remove ambiguity.  Also, if there are no numerical values, 
> would the string be considered a prefix or suffix?
The way I look at a version number, is that it is a sequence of tokens 
that are separated by some type of separator (space, dot, collon, 
perhaps a change from a number to a non-number or the other way around; 
whatever). What constitutes a separator between tokens should probably 
be configurable, with some sane default.

Each of these tokens is compared seperately, and may or may not be 
there. I'd suggest that a generic Qt solution only handles the case 
where a token is purely numeric. If the token is not numeric, it is 
either ignored or handed by an application specific handler (of which 
the virtual function above would be an example). The order would not 
really matter, IMHO. The non-numerical part may also be inbetween to 
numerical parts, like in Qt "5.3.0 beta 2". In my approach, the tokens 
to considder here would be 5, 3, 0, "beta", 2. The numerical ones should 
be handled by QVersion, the "beta" would not and would by default be 
ignored. So, by default, "5.3.0 rc 2" would compare equal to "5.3.0 beta 

If a token is not there, I think when comparing one should assume either 
a 0 for a numerical token and an empty string for a non-numerical one. 
So, Qt "5.3.0" would compare against "5.3.0 beta 2" as if it would have 
been 5, 3, 0, "", 0. That would mean that the vanilla class would 
compare QVersion("5.3.0") < QVersion("5.3.0 beta 2") due to the 2 being 
bigger than the 0 and the "beta" being ignored. If you want to handle 
this case properly, you'll have to subclass and make a version that 
handles "beta", "alpha" and "rc", and makes "' compare as less than any 
of these, so QtSpecificVersion("5.3.0") > QtSpecificVersion("5.3.0 beta 
2"). A couple of well known, trivial versions may be provided perhaps.

An implementation of QtSpecificVersion would then perhaps look something 
like this:

class QtSpecificVersion: public QVersion
     bool isNonNumericalSectionLessThan(int section, QStringRef 
otherSectionString) const
         if (section != 4) // we only expect "beta" or "rc" as the 
fourth token
             return false;

         QStringRef thisSectionString = sectionString(section);

         int value = valueForString(thisSectionString);
         int otherValue = valueForString(otherSectionString);

         return (otherValue < value);

     int valueForString(QStringRef string) const
         if (string.isEmpty())
             return 9;
         if (string == "alpha")
             return 1;
         if (string == "beta")
             return 2;
         if (string == "rc")
             return 3;

Anyone who has to deal with complex schemes where "aa" should compare as 
bigger than "z" can go right ahead and reimplement 
isNonNumericalSectionLessThan to their liking. I think may more people 
will stick with a simpeler scheme that just uses something like "2.1.5". 
If they don't want to subclass and still use beta, alpha or rc labels, 
they could just include a build number into their version number and 
have it always work fine: " beta 1" compares fine by default 
with " rc 3" by default in such a system.

Anyway: just an idea to keep it simple yet usable IMHO. Feel free to 
ignore ;-)


-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.qt-project.org/pipermail/development/attachments/20140514/87bf5ac8/attachment.html>

More information about the Development mailing list