strtonum.cpp revision 96ad23a1e9654a4d8a80b6e93f5794a3aacb0724
/* $Id$ */
/** @file
* IPRT - String To Number Convertion.
*/
/*
* Copyright (C) 2006-2007 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* The contents of this file may alternatively be used under the terms
* of the Common Development and Distribution License Version 1.0
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the
* VirtualBox OSE distribution, in which case the provisions of the
* CDDL are applicable instead of those of the GPL.
*
* You may elect to license modified versions of this file under the
* terms and conditions of either the GPL or the CDDL or both.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
/*******************************************************************************
* Global Variables *
*******************************************************************************/
/** 8-bit char -> digit. */
static const unsigned char g_auchDigits[256] =
{
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255,
255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255,
255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255
};
/** Approximated overflow shift checks. */
static const char g_auchShift[36] =
{
/* 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 */
64, 64, 63, 63, 62, 62, 62, 62, 61, 61, 61, 61, 61, 61, 61, 61, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 60, 59, 59, 59, 59
};
/*
#include <stdio.h>
int main()
{
int i;
printf("static const unsigned char g_auchDigits[256] =\n"
"{");
for (i = 0; i < 256; i++)
{
int ch = 255;
if (i >= '0' && i <= '9')
ch = i - '0';
else if (i >= 'a' && i <= 'z')
ch = i - 'a' + 10;
else if (i >= 'A' && i <= 'Z')
ch = i - 'A' + 10;
if (i == 0)
printf("\n %3d", ch);
else if ((i % 32) == 0)
printf(",\n %3d", ch);
else
printf(",%3d", ch);
}
printf("\n"
"};\n");
return 0;
}
*/
/**
* Converts a string representation of a version number to an unsigned number.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_TRAILING_CHARS
* @retval VWRN_TRAILING_SPACES
* @retval VINF_SUCCESS
* @retval VERR_NO_MEMORY
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param pu32 Where to store the converted number.
*
* @todo r=bird: The returned value isn't really suitable for comparing two
* version strings. Try see which result you get when converting
* "3.0.14" and "3.1.0" and comparing the values. The way to fix this
* deficiency would be to convert the individual parts and dividing the
* return value into sections: bits 31:24 FirstNumber; 23:16 Second;
* 15:8 Third; 7:0 Forth. It would probably be a good idea to use a
* 64-bit return value instead of a 32-bit one, so there is room for
* revision number when found.
*
* Actually, because of the above, the kind of API I had in mind was
* int RTStrVersionCompare(const char *pszVer1, const char *pszVer2).
* It wouldn't try convert input to numbers, just do a parallel parse.
* number of dots and dashes.
*/
{
return VERR_NO_MEMORY;
unsigned i = 0;
bool fLastInvalid = false;
while ( psz
&& *psz != '\0')
{
if (fLastInvalid)
{
if ( *psz == '-'
|| *psz == '_')
fLastInvalid = false;
}
else
{
if (RT_C_IS_DIGIT(*psz))
else if ( *psz != '.'
&& i == 0)
fLastInvalid = true;
}
psz++;
}
pszNew[i] = '\0';
/* Convert final number string to number */
int rc;
if (fLastInvalid)
{
*pu32 = 0;
rc = VERR_NO_DIGITS;
}
else
{
if (rc != VINF_SUCCESS)
*pu32 = 0;
}
return rc;
}
/**
* Converts a string representation of a number to a 64-bit unsigned number.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_NEGATIVE_UNSIGNED
* @retval VWRN_TRAILING_CHARS
* @retval VWRN_TRAILING_SPACES
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param ppszNext Where to store the pointer to the first char following the number. (Optional)
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pu64 Where to store the converted number. (optional)
*/
{
int iShift;
int rc;
unsigned char uch;
/*
*/
bool fPositive = true;
for (;; psz++)
{
if (*psz == '+')
fPositive = true;
else if (*psz == '-')
else
break;
}
/*
* Check for hex prefix.
*/
if (!uBase)
{
if ( psz[0] == '0'
{
uBase = 16;
psz += 2;
}
else if ( psz[0] == '0'
{
uBase = 8;
psz++;
}
else
uBase = 10;
}
else if ( uBase == 16
&& psz[0] == '0'
psz += 2;
/*
* Interpret the value.
* Note: We only support ascii digits at this time... :-)
*/
rc = VINF_SUCCESS;
u64 = 0;
{
break;
psz++;
}
if (!fPositive)
{
if (rc == VINF_SUCCESS)
}
if (pu64)
rc = VERR_NO_DIGITS;
if (ppszNext)
/*
*/
if ( rc == VINF_SUCCESS
&& *psz)
{
psz++;
}
return rc;
}
/**
* Converts a string representation of a number to a 64-bit unsigned number,
* making sure the full string is converted.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_NEGATIVE_UNSIGNED
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
* @retval VERR_TRAILING_SPACES
* @retval VERR_TRAILING_CHARS
*
* @param pszValue Pointer to the string value.
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pu64 Where to store the converted number. (optional)
*/
{
char *psz;
{
else
{
psz++;
}
}
return rc;
}
/**
* Converts a string representation of a number to a 64-bit unsigned number.
* The base is guessed.
*
* @returns 64-bit unsigned number on success.
* @returns 0 on failure.
* @param pszValue Pointer to the string value.
*/
{
if (RT_SUCCESS(rc))
return u64;
return 0;
}
/**
* Converts a string representation of a number to a 32-bit unsigned number.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_NEGATIVE_UNSIGNED
* @retval VWRN_TRAILING_CHARS
* @retval VWRN_TRAILING_SPACES
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param ppszNext Where to store the pointer to the first char following the number. (Optional)
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pu32 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffffffffULL)
}
if (pu32)
return rc;
}
/**
* Converts a string representation of a number to a 32-bit unsigned number,
* making sure the full string is converted.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_NEGATIVE_UNSIGNED
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
* @retval VERR_TRAILING_SPACES
* @retval VERR_TRAILING_CHARS
*
* @param pszValue Pointer to the string value.
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pu32 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffffffffULL)
}
if (pu32)
return rc;
}
/**
* Converts a string representation of a number to a 64-bit unsigned number.
* The base is guessed.
*
* @returns 32-bit unsigned number on success.
* @returns 0 on failure.
* @param pszValue Pointer to the string value.
*/
{
if (RT_SUCCESS(rc))
return u32;
return 0;
}
/**
* Converts a string representation of a number to a 16-bit unsigned number.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_NEGATIVE_UNSIGNED
* @retval VWRN_TRAILING_CHARS
* @retval VWRN_TRAILING_SPACES
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param ppszNext Where to store the pointer to the first char following the number. (Optional)
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pu16 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffffULL)
}
if (pu16)
return rc;
}
/**
* Converts a string representation of a number to a 16-bit unsigned number,
* making sure the full string is converted.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_NEGATIVE_UNSIGNED
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
* @retval VERR_TRAILING_SPACES
* @retval VERR_TRAILING_CHARS
*
* @param pszValue Pointer to the string value.
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pu16 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffffULL)
}
if (pu16)
return rc;
}
/**
* Converts a string representation of a number to a 16-bit unsigned number.
* The base is guessed.
*
* @returns 16-bit unsigned number on success.
* @returns 0 on failure.
* @param pszValue Pointer to the string value.
*/
{
if (RT_SUCCESS(rc))
return u16;
return 0;
}
/**
* Converts a string representation of a number to a 8-bit unsigned number.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_NEGATIVE_UNSIGNED
* @retval VWRN_TRAILING_CHARS
* @retval VWRN_TRAILING_SPACES
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param ppszNext Where to store the pointer to the first char following the number. (Optional)
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pu8 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffULL)
}
if (pu8)
return rc;
}
/**
* Converts a string representation of a number to a 8-bit unsigned number,
* making sure the full string is converted.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_NEGATIVE_UNSIGNED
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
* @retval VERR_TRAILING_SPACES
* @retval VERR_TRAILING_CHARS
*
* @param pszValue Pointer to the string value.
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pu8 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffULL)
}
if (pu8)
return rc;
}
/**
* Converts a string representation of a number to a 8-bit unsigned number.
* The base is guessed.
*
* @returns 8-bit unsigned number on success.
* @returns 0 on failure.
* @param pszValue Pointer to the string value.
*/
{
if (RT_SUCCESS(rc))
return u8;
return 0;
}
/**
* Converts a string representation of a number to a 64-bit signed number.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_TRAILING_CHARS
* @retval VWRN_TRAILING_SPACES
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param ppszNext Where to store the pointer to the first char following the number. (Optional)
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pi64 Where to store the converted number. (optional)
*/
{
int iShift;
int rc;
unsigned char uch;
/*
*/
bool fPositive = true;
for (;; psz++)
{
if (*psz == '+')
fPositive = true;
else if (*psz == '-')
else
break;
}
/*
* Check for hex prefix.
*/
if (!uBase)
{
if ( *psz == '0'
{
uBase = 16;
psz += 2;
}
else if ( *psz == '0'
{
uBase = 8;
psz++;
}
else
uBase = 10;
}
else if ( uBase == 16
&& *psz == '0'
psz += 2;
/*
* Interpret the value.
* Note: We only support ascii digits at this time... :-)
*/
rc = VINF_SUCCESS;
i64 = 0;
{
break;
psz++;
}
if (!fPositive)
if (pi64)
rc = VERR_NO_DIGITS;
if (ppszNext)
/*
*/
if ( rc == VINF_SUCCESS
&& *psz)
{
psz++;
}
return rc;
}
/**
* Converts a string representation of a number to a 64-bit signed number,
* making sure the full string is converted.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VINF_SUCCESS
* @retval VERR_TRAILING_CHARS
* @retval VERR_TRAILING_SPACES
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pi64 Where to store the converted number. (optional)
*/
{
char *psz;
{
else
{
psz++;
}
}
return rc;
}
/**
* Converts a string representation of a number to a 64-bit signed number.
* The base is guessed.
*
* @returns 64-bit signed number on success.
* @returns 0 on failure.
* @param pszValue Pointer to the string value.
*/
{
if (RT_SUCCESS(rc))
return i64;
return 0;
}
/**
* Converts a string representation of a number to a 32-bit signed number.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_TRAILING_CHARS
* @retval VWRN_TRAILING_SPACES
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param ppszNext Where to store the pointer to the first char following the number. (Optional)
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pi32 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
}
if (pi32)
return rc;
}
/**
* Converts a string representation of a number to a 32-bit signed number,
* making sure the full string is converted.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VINF_SUCCESS
* @retval VERR_TRAILING_CHARS
* @retval VERR_TRAILING_SPACES
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pi32 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
}
if (pi32)
return rc;
}
/**
* Converts a string representation of a number to a 32-bit signed number.
* The base is guessed.
*
* @returns 32-bit signed number on success.
* @returns 0 on failure.
* @param pszValue Pointer to the string value.
*/
{
if (RT_SUCCESS(rc))
return i32;
return 0;
}
/**
* Converts a string representation of a number to a 16-bit signed number.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_TRAILING_CHARS
* @retval VWRN_TRAILING_SPACES
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param ppszNext Where to store the pointer to the first char following the number. (Optional)
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pi16 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
}
if (pi16)
return rc;
}
/**
* Converts a string representation of a number to a 16-bit signed number,
* making sure the full string is converted.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VINF_SUCCESS
* @retval VERR_TRAILING_CHARS
* @retval VERR_TRAILING_SPACES
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pi16 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
}
if (pi16)
return rc;
}
/**
* Converts a string representation of a number to a 16-bit signed number.
* The base is guessed.
*
* @returns 16-bit signed number on success.
* @returns 0 on failure.
* @param pszValue Pointer to the string value.
*/
{
if (RT_SUCCESS(rc))
return i16;
return 0;
}
/**
* Converts a string representation of a number to a 8-bit signed number.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VWRN_TRAILING_CHARS
* @retval VWRN_TRAILING_SPACES
* @retval VINF_SUCCESS
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param ppszNext Where to store the pointer to the first char following the number. (Optional)
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pi8 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
}
if (pi8)
return rc;
}
/**
* Converts a string representation of a number to a 8-bit signed number,
* making sure the full string is converted.
*
* @returns iprt status code.
* Warnings are used to indicate convertion problems.
* @retval VWRN_NUMBER_TOO_BIG
* @retval VINF_SUCCESS
* @retval VERR_TRAILING_CHARS
* @retval VERR_TRAILING_SPACES
* @retval VERR_NO_DIGITS
*
* @param pszValue Pointer to the string value.
* @param uBase The base of the representation used.
* If the function will look for known prefixes before defaulting to 10.
* @param pi8 Where to store the converted number. (optional)
*/
{
if (RT_SUCCESS(rc))
{
}
if (pi8)
return rc;
}
/**
* Converts a string representation of a number to a 8-bit signed number.
* The base is guessed.
*
* @returns 8-bit signed number on success.
* @returns 0 on failure.
* @param pszValue Pointer to the string value.
*/
{
if (RT_SUCCESS(rc))
return i8;
return 0;
}