VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/string/strversion.cpp@ 25005

Last change on this file since 25005 was 25005, checked in by vboxsync, 15 years ago

IPRT: Optimized version of RTStrVersionCompare (thanks to Knut!), made it behave like strcmp().

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 4.6 KB
Line 
1/* $Id: strversion.cpp 25005 2009-11-26 14:42:59Z vboxsync $ */
2/** @file
3 * IPRT - Version String Parsing.
4 */
5
6/*
7 * Copyright (C) 2009 Sun Microsystems, Inc.
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 *
26 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
27 * Clara, CA 95054 USA or visit http://www.sun.com if you need
28 * additional information or have any questions.
29 */
30
31
32/*******************************************************************************
33* Header Files *
34*******************************************************************************/
35#include <iprt/string.h>
36#include "internal/iprt.h"
37
38#include <iprt/assert.h>
39#include <iprt/ctype.h>
40#include <iprt/err.h>
41
42
43/*******************************************************************************
44* Defined Constants And Macros *
45*******************************************************************************/
46#define RTSTRVER_IS_PUNCTUACTION(ch) \
47 ( (ch) == '_' || (ch) == '-' || (ch) == '+' || RT_C_IS_PUNCT(ch) )
48
49
50/**
51 * Parses a out the next block from a version string.
52 *
53 * @returns true if numeric, false if not.
54 * @param ppszVer The string cursor, IN/OUT.
55 * @param pu32Value Where to return the value if numeric.
56 * @param pcchBlock Where to return the block length.
57 */
58static bool rtStrVersionParseBlock(const char **ppszVer, uint32_t *pu32Value, size_t *pcchBlock)
59{
60 const char *psz = *ppszVer;
61
62 /* Check for end-of-string. */
63 if (!*psz)
64 {
65 *pu32Value = 0;
66 *pcchBlock = 0;
67 return false;
68 }
69
70 bool fNumeric = RT_C_IS_DIGIT(*psz);
71 if (fNumeric)
72 {
73 do
74 psz++;
75 while (*psz && RT_C_IS_DIGIT(*psz));
76
77 char *pszNext;
78 int rc = RTStrToUInt32Ex(*ppszVer, &pszNext, 10, pu32Value);
79 AssertRC(rc);
80 Assert(pszNext == psz);
81 if (RT_FAILURE(rc) || rc == VWRN_NUMBER_TOO_BIG)
82 {
83 fNumeric = false;
84 *pu32Value = 0;
85 }
86 }
87 else
88 {
89 do
90 psz++;
91 while (*psz && !RT_C_IS_DIGIT(*psz) && !RTSTRVER_IS_PUNCTUACTION(*psz));
92 *pu32Value = 0;
93 }
94 *pcchBlock = psz - *ppszVer;
95
96 /* skip punctuation */
97 if (RTSTRVER_IS_PUNCTUACTION(*psz))
98 psz++;
99 *ppszVer = psz;
100
101 return fNumeric;
102}
103
104
105RTDECL(int) RTStrVersionCompare(const char *pszVer1, const char *pszVer2)
106{
107 AssertPtr(pszVer1);
108 AssertPtr(pszVer2);
109
110 /*
111 * Do a parallel parse of the strings.
112 */
113 int iRes = 0;
114 while (*pszVer1 || *pszVer2)
115 {
116 const char *pszBlock1 = pszVer1;
117 size_t cchBlock1;
118 uint32_t uVal1;
119 bool fNumeric1 = rtStrVersionParseBlock(&pszVer1, &uVal1, &cchBlock1);
120
121 const char *pszBlock2 = pszVer2;
122 size_t cchBlock2;
123 uint32_t uVal2;
124 bool fNumeric2 = rtStrVersionParseBlock(&pszVer2, &uVal2, &cchBlock2);
125
126 if (fNumeric1 && fNumeric2)
127 {
128 if (uVal1 != uVal2)
129 {
130 iRes = uVal1 > uVal2 ? 1 : 2;
131 break;
132 }
133 }
134 else if ( !fNumeric1 && fNumeric2 && uVal2 == 0 && cchBlock1 == 0
135 || !fNumeric2 && fNumeric1 && uVal1 == 0 && cchBlock2 == 0
136 )
137 {
138 /* 1.0 == 1.0.0.0.0. */;
139 }
140 else
141 {
142 int iDiff = RTStrNICmp(pszBlock1, pszBlock2, RT_MIN(cchBlock1, cchBlock2));
143 if (!iDiff && cchBlock1 != cchBlock2)
144 iDiff = cchBlock1 < cchBlock2 ? -1 : 1;
145 if (iDiff)
146 {
147 iRes = iDiff > 0 ? 1 : 2;
148 break;
149 }
150 }
151 }
152 return iRes;
153}
154RT_EXPORT_SYMBOL(RTStrVersionCompare);
Note: See TracBrowser for help on using the repository browser.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette