VirtualBox

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

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

Automated rebranding to Oracle copyright/license strings via filemuncher

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 5.8 KB
Line 
1/* $Id: strversion.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
2/** @file
3 * IPRT - Version String Parsing.
4 */
5
6/*
7 * Copyright (C) 2009 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. 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
27
28/*******************************************************************************
29* Header Files *
30*******************************************************************************/
31#include <iprt/string.h>
32#include "internal/iprt.h"
33
34#include <iprt/assert.h>
35#include <iprt/ctype.h>
36#include <iprt/err.h>
37
38
39/*******************************************************************************
40* Defined Constants And Macros *
41*******************************************************************************/
42#define RTSTRVER_IS_PUNCTUACTION(ch) \
43 ( (ch) == '_' || (ch) == '-' || (ch) == '+' || RT_C_IS_PUNCT(ch) )
44
45
46/**
47 * Parses a out the next block from a version string.
48 *
49 * @returns true if numeric, false if not.
50 * @param ppszVer The string cursor, IN/OUT.
51 * @param pi32Value Where to return the value if numeric.
52 * @param pcchBlock Where to return the block length.
53 */
54static bool rtStrVersionParseBlock(const char **ppszVer, int32_t *pi32Value, size_t *pcchBlock)
55{
56 const char *psz = *ppszVer;
57
58 /* Check for end-of-string. */
59 if (!*psz)
60 {
61 *pi32Value = 0;
62 *pcchBlock = 0;
63 return false;
64 }
65
66 bool fNumeric = RT_C_IS_DIGIT(*psz);
67 if (fNumeric)
68 {
69 do
70 psz++;
71 while (*psz && RT_C_IS_DIGIT(*psz));
72
73 int rc = RTStrToInt32Ex(*ppszVer, NULL, 10, pi32Value);
74 if (RT_FAILURE(rc) || rc == VWRN_NUMBER_TOO_BIG)
75 {
76 AssertRC(rc);
77 fNumeric = false;
78 *pi32Value = 0;
79 }
80 }
81 else
82 {
83 do
84 psz++;
85 while (*psz && !RT_C_IS_DIGIT(*psz) && !RTSTRVER_IS_PUNCTUACTION(*psz));
86 size_t cchBlock = psz - *ppszVer;
87
88 /* Translate standard pre release terms to negative values. */
89 int32_t iVal1;
90 if ( cchBlock == 2 && !RTStrNICmp(*ppszVer, "RC", 2))
91 iVal1 = -100000;
92 else if (cchBlock == 3 && !RTStrNICmp(*ppszVer, "PRE", 3))
93 iVal1 = -200000;
94 else if (cchBlock == 5 && !RTStrNICmp(*ppszVer, "GAMMA", 5))
95 iVal1 = -300000;
96 else if (cchBlock == 4 && !RTStrNICmp(*ppszVer, "BETA", 4))
97 iVal1 = -400000;
98 else if (cchBlock == 5 && !RTStrNICmp(*ppszVer, "ALPHA", 5))
99 iVal1 = -500000;
100 else
101 iVal1 = 0;
102 if (iVal1 != 0)
103 {
104 /* Trailing number? Add it assuming BETA == BETA1. */
105 if (RT_C_IS_DIGIT(*psz))
106 {
107 const char *psz2 = psz;
108 do
109 psz++;
110 while (*psz && !RT_C_IS_DIGIT(*psz) && !RTSTRVER_IS_PUNCTUACTION(*psz));
111
112 int rc = RTStrToInt32Ex(psz2, NULL, 10, pi32Value);
113 if (RT_SUCCESS(rc) && rc != VWRN_NUMBER_TOO_BIG && *pi32Value)
114 iVal1 += *pi32Value - 1;
115 else
116 {
117 AssertRC(rc);
118 psz = psz2;
119 }
120 }
121 fNumeric = true;
122 }
123 *pi32Value = iVal1;
124 }
125 *pcchBlock = psz - *ppszVer;
126
127 /* skip punctuation */
128 if (RTSTRVER_IS_PUNCTUACTION(*psz))
129 psz++;
130 *ppszVer = psz;
131
132 return fNumeric;
133}
134
135
136RTDECL(int) RTStrVersionCompare(const char *pszVer1, const char *pszVer2)
137{
138 AssertPtr(pszVer1);
139 AssertPtr(pszVer2);
140
141 /*
142 * Do a parallel parse of the strings.
143 */
144 while (*pszVer1 || *pszVer2)
145 {
146 const char *pszBlock1 = pszVer1;
147 size_t cchBlock1;
148 int32_t iVal1;
149 bool fNumeric1 = rtStrVersionParseBlock(&pszVer1, &iVal1, &cchBlock1);
150
151 const char *pszBlock2 = pszVer2;
152 size_t cchBlock2;
153 int32_t iVal2;
154 bool fNumeric2 = rtStrVersionParseBlock(&pszVer2, &iVal2, &cchBlock2);
155
156 if (fNumeric1 && fNumeric2)
157 {
158 if (iVal1 != iVal2)
159 return iVal1 < iVal2 ? -1 : 1;
160 }
161 else if ( fNumeric1 != fNumeric2
162 && ( fNumeric1
163 ? iVal1 == 0 && cchBlock2 == 0
164 : iVal2 == 0 && cchBlock1 == 0)
165 )
166 {
167 /*else: 1.0 == 1.0.0.0.0. */;
168 }
169 else if ( fNumeric1 != fNumeric2
170 && (fNumeric1 ? iVal1 : iVal2) < 0)
171 {
172 /* Pre-release indicators are smaller than all other strings. */
173 return fNumeric1 ? -1 : 1;
174 }
175 else
176 {
177 int iDiff = RTStrNICmp(pszBlock1, pszBlock2, RT_MIN(cchBlock1, cchBlock2));
178 if (!iDiff && cchBlock1 != cchBlock2)
179 iDiff = cchBlock1 < cchBlock2 ? -1 : 1;
180 if (iDiff)
181 return iDiff < 0 ? -1 : 1;
182 }
183 }
184 return 0;
185}
186RT_EXPORT_SYMBOL(RTStrVersionCompare);
Note: See TracBrowser for help on using the repository browser.

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