Comperio
7th January 2005 06:25 UTC
Comparing 2 versions
I was searching for a function that could compare 2 version numbers. I liked the example at http://nsis.sourceforge.net/archive/....php?page=643, but I did find a small flaw with this example in that it would see "3.1.0" and "3.10.0" as identical versions.
I was having a hard time stepping through the code, so I decided to write my own variation. I've tested every possible scenerio I could think of and could not make it fail. It will handle from 1 to up to 4 sections (ex: "1.2.3.4") as long as the version number string consists of strictly numbers (no letters).
The code is attached. It's easy to follow and contains much documentation, so it should be easy enough for anyone to follow the logic.
Any questions? Just let me know.
Enjoy!
kichik
7th January 2005 11:45 UTC
Everyone can create Archive pages. You can go ahead and create one for this function too.
bluenet
7th January 2005 14:05 UTC
These is a VerCmp function rip from my NSIS Header File.
Use it like StrFunc.
Exsample: ${VerCmp} $0 1.0.10.3 1.0.1.9
In this case $0 = 1 (1.0.10.3 > 1.0.1.9)
${VerCmp} $0 1.0.1.15 1.0.2
This case $0 = -1 (1.0.1.15 < 1.0.2)
And return 0 if equal.
A litte difference with StrFunc: Uninstall function is ${un.VerCmp} not ${UnVerCmp}
macro DEFINE_FUNC NAME
!define `${NAME}` `!insertmacro INSERT_FUNC_${NAME} "${NAME}" ""`
!
define `un.${NAME}` `!insertmacro INSERT_FUNC_${NAME} "${NAME}" "un."`
!macroend
>!macro DEFINE_CALL NAME UNFIX
!undef `${UNFIX}${NAME}`
!define `${UNFIX}${NAME}` `!insertmacro CALL_FUNC_${NAME} "${NAME}" "${UNFIX}"`
!macroend
>###############################################################
# º¯Êý: VerCmp
###############################################################
>!insertmacro DEFINE_FUNC VerCmp
>!macro CALL_FUNC_VerCmp NAME UNFIX ResultVar Ver1 Ver2
Push`${Ver2}`
Push `${Ver1}`
Call ${UNFIX}${NAME}
Pop ${ResultVar}
!macroend
>!macro INSERT_FUNC_VerCmp NAME UNFIX
Function ${UNFIX}${NAME}
Exch $R0
Exch
Exch $R1
Push $R2
Push $R3
${Do}
${If}$R0 != ""
Push $R0
Call${UNFIX}${NAME}.FindDot
Pop $R0;µãºóÃæµÄ
Pop $R2;µãÇ°ÃæµÄ
${Else}
StrCpy $R2 0
${EndIf}
${If}$R1 != ""
Push $R1
Call${UNFIX}${NAME}.FindDot
Pop $R1;µãºóÃæµÄ
Pop $R3;µãÇ°ÃæµÄ
${Else}
StrCpy $R3 0
${EndIf}
${If}$R2 > $R3
StrCpy $R0 1
${ExitDo}
${ElseIf}$R2 < $R3
StrCpy $R0-1
${ExitDo}
${EndIf}
${If}$R0 == ""
${AndIf} $R1 == ""
StrCpy $R0 0
${ExitDo}
${EndIf}
${loop}
Pop $R3
Pop $R2
Pop $R1
Exch $R0
FunctionEnd
Function ${UNFIX}${NAME}.FindDot
Exch $R0
Push $R1
Push $R2
Push $R3
StrCpy $R2 0
${Do}
StrCpy $R3 $R0 1 $R2
${If} $R3 == "."
StrCpy $R1 $R0 $R2
IntOp $R2 $R2+ 1
StrCpy $R0 $R0"" $R2
${ExitDo}
${EndIf}
${If}$R3 == ""
StrCpy $R1 $R0
StrCpy $R0 ""
${ExitDo}
${EndIf}
IntOp $R2 $R2 + 1
${Loop}
Pop $R3
Pop $R2
Exch $R1
Exch
Exch $R0
FunctionEnd
!insertmacro DEFINE_CALL `${NAME}` `${UNFIX}`
!macroend
>
Comperio
9th January 2005 20:07 UTC
I was not aware that I could post directly to the NSIS archive. (Very cool!)
I took kichik's advise and the code is now located at http://nsis.sourceforge.net/archive/...instances=0,11
I did do a little tweaking to add some POP commands to restore the contents of the stack.
(By the way, I think NSIS kicks butt!)
Afrow UK
10th January 2005 09:14 UTC
I have found the problem with my function. I shall fix it when I get home!
-Stu
stb
10th January 2005 15:47 UTC
NSIS Archive contains another one:
http://nsis.sourceforge.net/archive/....php?pageid=57
Looks good to me.
Afrow UK
10th January 2005 20:17 UTC
That VersionCheck function fails on version numbers like 6 and 6.0 (it says 6 is lower than 6.0 when they are the same!)
-Stu
Afrow UK
10th January 2005 22:14 UTC
Ok, I finished the function. I re-wrote it taking a different approach from the old function...
The previous function (VersionCheckNew) would strip the dot's, make the two numbers the same length (by adding leading 0's) then making both numbers proper integers by placing 1 in front of them.
This worked for a while until Comperio found that it would fail on e.g. 3.1.0 and 3.10.0
Here, the second version is obviously higher.
In the old function, 3.1.0 would become 13100 and 3.10.0 would become 13100. As you can see, both integers are exactly the same and thus the function would falsely report that both versions numbers are the same!
This function differs in that it compares each number between the dot's one by one, from start to finish.
There's another version string type that I never tried before... something like this:
1.01
1.10
This function doesn't break on that either.
http://nsis.sourceforge.net/archive/...ances=0,11,122
-Stu