strversion.cpp revision 29e50fce8a16b6c8955f48b7d1e19cb7aa3694dd
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/* $Id$ */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/** @file
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * IPRT - Version String Parsing.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*
c58f1213e628a545081c70e26c6b67a841cff880vboxsync * Copyright (C) 2009 Sun Microsystems, Inc.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * available from http://www.virtualbox.org. This file is free software;
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * you can redistribute it and/or modify it under the terms of the GNU
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * General Public License (GPL) as published by the Free Software
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
6ec4e1827eab6a424d672ef0e5a17b065e52db20vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * The contents of this file may alternatively be used under the terms
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * of the Common Development and Distribution License Version 1.0
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * VirtualBox OSE distribution, in which case the provisions of the
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * CDDL are applicable instead of those of the GPL.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * You may elect to license modified versions of this file under the
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * terms and conditions of either the GPL or the CDDL or both.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * additional information or have any questions.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Header Files *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/string.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include "internal/iprt.h"
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/assert.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/ctype.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync#include <iprt/err.h>
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/*******************************************************************************
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync* Defined Constants And Macros *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync*******************************************************************************/
98427c0ab08697e468c26dc33ee9571308577867vboxsync#define RTSTRVER_IS_PUNCTUACTION(ch) \
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync ( (ch) == '_' || (ch) == '-' || (ch) == '+' || RT_C_IS_PUNCT(ch) )
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync/**
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Parses a out the next block from a version string.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @returns true if numeric, false if not.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param ppszVer The string cursor, IN/OUT.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pu32Value Where to return the value if numeric.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * @param pcchBlock Where to return the block length.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncstatic bool rtStrVersionParseBlock(const char **ppszVer, uint32_t *pu32Value, size_t *pcchBlock)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const char *psz = *ppszVer;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* Check for end-of-string. */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!*psz)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *pu32Value = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *pcchBlock = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fNumeric = RT_C_IS_DIGIT(*psz);
98427c0ab08697e468c26dc33ee9571308577867vboxsync if (fNumeric)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync do
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync psz++;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync while (*psz && RT_C_IS_DIGIT(*psz));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
98427c0ab08697e468c26dc33ee9571308577867vboxsync char *pszNext;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int rc = RTStrToUInt32Ex(*ppszVer, &pszNext, 10, pu32Value);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertRC(rc);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync Assert(pszNext == psz);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RT_FAILURE(rc) || rc == VWRN_NUMBER_TOO_BIG)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync fNumeric = false;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *pu32Value = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync do
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync psz++;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync while (*psz && !RT_C_IS_DIGIT(*psz) && !RTSTRVER_IS_PUNCTUACTION(*psz));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *pu32Value = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *pcchBlock = psz - *ppszVer;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* skip punctuation */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (RTSTRVER_IS_PUNCTUACTION(*psz))
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync psz++;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync *ppszVer = psz;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return fNumeric;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncRTDECL(int) RTStrVersionCompare(const char *pszVer1, const char *pszVer2)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync{
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtr(pszVer1);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync AssertPtr(pszVer2);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /*
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync * Do a parallel parse of the strings.
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync */
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int iRes = 0;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync while (*pszVer1 || *pszVer2)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const char *pszBlock1 = pszVer1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t cchBlock1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint32_t uVal1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fNumeric1 = rtStrVersionParseBlock(&pszVer1, &uVal1, &cchBlock1);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync const char *pszBlock2 = pszVer2;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync size_t cchBlock2;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync uint32_t uVal2;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync bool fNumeric2 = rtStrVersionParseBlock(&pszVer2, &uVal2, &cchBlock2);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (fNumeric1 && fNumeric2)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (uVal1 != uVal2)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync iRes = uVal1 > uVal2 ? 1 : 2;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else if ( !fNumeric1 && fNumeric2 && uVal2 == 0 && cchBlock1 == 0
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync || !fNumeric2 && fNumeric1 && uVal1 == 0 && cchBlock2 == 0
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync )
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync /* 1.0 == 1.0.0.0.0. */;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync else
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync int iDiff = RTStrNICmp(pszBlock1, pszBlock2, RT_MIN(cchBlock1, cchBlock2));
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (!iDiff && cchBlock1 != cchBlock2)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync iDiff = cchBlock1 < cchBlock2 ? -1 : 1;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync if (iDiff)
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync {
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync iRes = iDiff > 0 ? 1 : 2;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync break;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync }
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync return iRes;
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync}
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsyncRT_EXPORT_SYMBOL(RTStrVersionCompare);
a33af978add1a03aab11b2895f441af5cb2a11a6vboxsync