strtonum.cpp revision f3ce8123823edcdc352ae29f877990bff36a84cb
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/* $Id$ */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/** @file
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * IPRT - String To Number Conversion.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/*
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Copyright (C) 2006-2007 Oracle Corporation
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * available from http://www.virtualbox.org. This file is free software;
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * you can redistribute it and/or modify it under the terms of the GNU
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * General Public License (GPL) as published by the Free Software
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * The contents of this file may alternatively be used under the terms
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * of the Common Development and Distribution License Version 1.0
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * VirtualBox OSE distribution, in which case the provisions of the
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * CDDL are applicable instead of those of the GPL.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * You may elect to license modified versions of this file under the
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync * terms and conditions of either the GPL or the CDDL or both.
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/*******************************************************************************
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync* Header Files *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync*******************************************************************************/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#include <iprt/string.h>
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#include "internal/iprt.h"
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#include <iprt/assert.h>
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#include <iprt/ctype.h> /* needed for RT_C_IS_DIGIT */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync#include <iprt/err.h>
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/*******************************************************************************
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync* Global Variables *
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync*******************************************************************************/
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync/** 8-bit char -> digit. */
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsyncstatic const unsigned char g_auchDigits[256] =
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync{
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync 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,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync 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,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync 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,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync 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,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync 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,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync 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,
b8e299dddd091ae24e0c08c45d91b8f937bd14d2vboxsync 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 number to a 64-bit unsigned number.
*
* @returns iprt status code.
* Warnings are used to indicate conversion 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)
*/
RTDECL(int) RTStrToUInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint64_t *pu64)
{
const char *psz = pszValue;
int iShift;
int rc;
uint64_t u64;
unsigned char uch;
/*
* Positive/Negative stuff.
*/
bool fPositive = true;
for (;; psz++)
{
if (*psz == '+')
fPositive = true;
else if (*psz == '-')
fPositive = !fPositive;
else
break;
}
/*
* Check for hex prefix.
*/
if (!uBase)
{
if ( psz[0] == '0'
&& (psz[1] == 'x' || psz[1] == 'X')
&& g_auchDigits[(unsigned char)psz[2]] < 16)
{
uBase = 16;
psz += 2;
}
else if ( psz[0] == '0'
&& g_auchDigits[(unsigned char)psz[1]] < 8)
{
uBase = 8;
psz++;
}
else
uBase = 10;
}
else if ( uBase == 16
&& psz[0] == '0'
&& (psz[1] == 'x' || psz[1] == 'X')
&& g_auchDigits[(unsigned char)psz[2]] < 16)
psz += 2;
/*
* Interpret the value.
* Note: We only support ascii digits at this time... :-)
*/
iShift = g_auchShift[uBase];
pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
rc = VINF_SUCCESS;
u64 = 0;
while ((uch = (unsigned char)*psz) != 0)
{
unsigned char chDigit = g_auchDigits[uch];
uint64_t u64Prev;
if (chDigit >= uBase)
break;
u64Prev = u64;
u64 *= uBase;
u64 += chDigit;
if (u64Prev > u64 || (u64Prev >> iShift))
rc = VWRN_NUMBER_TOO_BIG;
psz++;
}
if (!fPositive)
{
if (rc == VINF_SUCCESS)
rc = VWRN_NEGATIVE_UNSIGNED;
u64 = -(int64_t)u64;
}
if (pu64)
*pu64 = u64;
if (psz == pszValue)
rc = VERR_NO_DIGITS;
if (ppszNext)
*ppszNext = (char *)psz;
/*
* Warn about trailing chars/spaces.
*/
if ( rc == VINF_SUCCESS
&& *psz)
{
while (*psz == ' ' || *psz == '\t')
psz++;
rc = *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
}
return rc;
}
RT_EXPORT_SYMBOL(RTStrToUInt64Ex);
/**
* 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 conversion 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)
*/
RTDECL(int) RTStrToUInt64Full(const char *pszValue, unsigned uBase, uint64_t *pu64)
{
char *psz;
int rc = RTStrToUInt64Ex(pszValue, &psz, uBase, pu64);
if (RT_SUCCESS(rc) && *psz)
{
if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES)
rc = -rc;
else
{
while (*psz == ' ' || *psz == '\t')
psz++;
rc = *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES;
}
}
return rc;
}
RT_EXPORT_SYMBOL(RTStrToUInt64Full);
/**
* 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.
*/
RTDECL(uint64_t) RTStrToUInt64(const char *pszValue)
{
uint64_t u64;
int rc = RTStrToUInt64Ex(pszValue, NULL, 0, &u64);
if (RT_SUCCESS(rc))
return u64;
return 0;
}
RT_EXPORT_SYMBOL(RTStrToUInt64);
/**
* Converts a string representation of a number to a 32-bit unsigned number.
*
* @returns iprt status code.
* Warnings are used to indicate conversion 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)
*/
RTDECL(int) RTStrToUInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint32_t *pu32)
{
uint64_t u64;
int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffffffffULL)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pu32)
*pu32 = (uint32_t)u64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToUInt32Ex);
/**
* 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 conversion 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)
*/
RTDECL(int) RTStrToUInt32Full(const char *pszValue, unsigned uBase, uint32_t *pu32)
{
uint64_t u64;
int rc = RTStrToUInt64Full(pszValue, uBase, &u64);
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffffffffULL)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pu32)
*pu32 = (uint32_t)u64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToUInt32Full);
/**
* 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.
*/
RTDECL(uint32_t) RTStrToUInt32(const char *pszValue)
{
uint32_t u32;
int rc = RTStrToUInt32Ex(pszValue, NULL, 0, &u32);
if (RT_SUCCESS(rc))
return u32;
return 0;
}
RT_EXPORT_SYMBOL(RTStrToUInt32);
/**
* Converts a string representation of a number to a 16-bit unsigned number.
*
* @returns iprt status code.
* Warnings are used to indicate conversion 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)
*/
RTDECL(int) RTStrToUInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint16_t *pu16)
{
uint64_t u64;
int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffffULL)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pu16)
*pu16 = (uint16_t)u64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToUInt16Ex);
/**
* 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 conversion 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)
*/
RTDECL(int) RTStrToUInt16Full(const char *pszValue, unsigned uBase, uint16_t *pu16)
{
uint64_t u64;
int rc = RTStrToUInt64Full(pszValue, uBase, &u64);
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffffULL)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pu16)
*pu16 = (uint16_t)u64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToUInt16Full);
/**
* 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.
*/
RTDECL(uint16_t) RTStrToUInt16(const char *pszValue)
{
uint16_t u16;
int rc = RTStrToUInt16Ex(pszValue, NULL, 0, &u16);
if (RT_SUCCESS(rc))
return u16;
return 0;
}
RT_EXPORT_SYMBOL(RTStrToUInt16);
/**
* Converts a string representation of a number to a 8-bit unsigned number.
*
* @returns iprt status code.
* Warnings are used to indicate conversion 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)
*/
RTDECL(int) RTStrToUInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, uint8_t *pu8)
{
uint64_t u64;
int rc = RTStrToUInt64Ex(pszValue, ppszNext, uBase, &u64);
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffULL)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pu8)
*pu8 = (uint8_t)u64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToUInt8Ex);
/**
* 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 conversion 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)
*/
RTDECL(int) RTStrToUInt8Full(const char *pszValue, unsigned uBase, uint8_t *pu8)
{
uint64_t u64;
int rc = RTStrToUInt64Full(pszValue, uBase, &u64);
if (RT_SUCCESS(rc))
{
if (u64 & ~0xffULL)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pu8)
*pu8 = (uint8_t)u64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToUInt8Full);
/**
* 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.
*/
RTDECL(uint8_t) RTStrToUInt8(const char *pszValue)
{
uint8_t u8;
int rc = RTStrToUInt8Ex(pszValue, NULL, 0, &u8);
if (RT_SUCCESS(rc))
return u8;
return 0;
}
RT_EXPORT_SYMBOL(RTStrToUInt8);
/**
* Converts a string representation of a number to a 64-bit signed number.
*
* @returns iprt status code.
* Warnings are used to indicate conversion 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)
*/
RTDECL(int) RTStrToInt64Ex(const char *pszValue, char **ppszNext, unsigned uBase, int64_t *pi64)
{
const char *psz = pszValue;
int iShift;
int rc;
int64_t i64;
unsigned char uch;
/*
* Positive/Negative stuff.
*/
bool fPositive = true;
for (;; psz++)
{
if (*psz == '+')
fPositive = true;
else if (*psz == '-')
fPositive = !fPositive;
else
break;
}
/*
* Check for hex prefix.
*/
if (!uBase)
{
if ( *psz == '0'
&& (psz[1] == 'x' || psz[1] == 'X')
&& g_auchDigits[(unsigned char)psz[2]] < 16)
{
uBase = 16;
psz += 2;
}
else if ( *psz == '0'
&& g_auchDigits[(unsigned char)psz[1]] < 8)
{
uBase = 8;
psz++;
}
else
uBase = 10;
}
else if ( uBase == 16
&& *psz == '0'
&& (psz[1] == 'x' || psz[1] == 'X')
&& g_auchDigits[(unsigned char)psz[2]] < 16)
psz += 2;
/*
* Interpret the value.
* Note: We only support ascii digits at this time... :-)
*/
iShift = g_auchShift[uBase]; /** @todo test this, it's probably not 100% right yet. */
pszValue = psz; /* (Prefix and sign doesn't count in the digit counting.) */
rc = VINF_SUCCESS;
i64 = 0;
while ((uch = (unsigned char)*psz) != 0)
{
unsigned char chDigit = g_auchDigits[uch];
int64_t i64Prev;
if (chDigit >= uBase)
break;
i64Prev = i64;
i64 *= uBase;
i64 += chDigit;
if (i64Prev > i64 || (i64Prev >> iShift))
rc = VWRN_NUMBER_TOO_BIG;
psz++;
}
if (!fPositive)
i64 = -i64;
if (pi64)
*pi64 = i64;
if (psz == pszValue)
rc = VERR_NO_DIGITS;
if (ppszNext)
*ppszNext = (char *)psz;
/*
* Warn about trailing chars/spaces.
*/
if ( rc == VINF_SUCCESS
&& *psz)
{
while (*psz == ' ' || *psz == '\t')
psz++;
rc = *psz ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
}
return rc;
}
RT_EXPORT_SYMBOL(RTStrToInt64Ex);
/**
* 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 conversion 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)
*/
RTDECL(int) RTStrToInt64Full(const char *pszValue, unsigned uBase, int64_t *pi64)
{
char *psz;
int rc = RTStrToInt64Ex(pszValue, &psz, uBase, pi64);
if (RT_SUCCESS(rc) && *psz)
{
if (rc == VWRN_TRAILING_CHARS || rc == VWRN_TRAILING_SPACES)
rc = -rc;
else
{
while (*psz == ' ' || *psz == '\t')
psz++;
rc = *psz ? VERR_TRAILING_CHARS : VERR_TRAILING_SPACES;
}
}
return rc;
}
RT_EXPORT_SYMBOL(RTStrToInt64Full);
/**
* 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.
*/
RTDECL(int64_t) RTStrToInt64(const char *pszValue)
{
int64_t i64;
int rc = RTStrToInt64Ex(pszValue, NULL, 0, &i64);
if (RT_SUCCESS(rc))
return i64;
return 0;
}
RT_EXPORT_SYMBOL(RTStrToInt64);
/**
* Converts a string representation of a number to a 32-bit signed number.
*
* @returns iprt status code.
* Warnings are used to indicate conversion 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)
*/
RTDECL(int) RTStrToInt32Ex(const char *pszValue, char **ppszNext, unsigned uBase, int32_t *pi32)
{
int64_t i64;
int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
if (RT_SUCCESS(rc))
{
int32_t i32 = (int32_t)i64;
if (i64 != (int64_t)i32)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pi32)
*pi32 = (int32_t)i64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToInt32Ex);
/**
* 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 conversion 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)
*/
RTDECL(int) RTStrToInt32Full(const char *pszValue, unsigned uBase, int32_t *pi32)
{
int64_t i64;
int rc = RTStrToInt64Full(pszValue, uBase, &i64);
if (RT_SUCCESS(rc))
{
int32_t i32 = (int32_t)i64;
if (i64 != (int64_t)i32)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pi32)
*pi32 = (int32_t)i64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToInt32Full);
/**
* 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.
*/
RTDECL(int32_t) RTStrToInt32(const char *pszValue)
{
int32_t i32;
int rc = RTStrToInt32Ex(pszValue, NULL, 0, &i32);
if (RT_SUCCESS(rc))
return i32;
return 0;
}
RT_EXPORT_SYMBOL(RTStrToInt32);
/**
* Converts a string representation of a number to a 16-bit signed number.
*
* @returns iprt status code.
* Warnings are used to indicate conversion 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)
*/
RTDECL(int) RTStrToInt16Ex(const char *pszValue, char **ppszNext, unsigned uBase, int16_t *pi16)
{
int64_t i64;
int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
if (RT_SUCCESS(rc))
{
int16_t i16 = (int16_t)i64;
if (i64 != (int64_t)i16)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pi16)
*pi16 = (int16_t)i64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToInt16Ex);
/**
* 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 conversion 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)
*/
RTDECL(int) RTStrToInt16Full(const char *pszValue, unsigned uBase, int16_t *pi16)
{
int64_t i64;
int rc = RTStrToInt64Full(pszValue, uBase, &i64);
if (RT_SUCCESS(rc))
{
int16_t i16 = (int16_t)i64;
if (i64 != (int64_t)i16)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pi16)
*pi16 = (int16_t)i64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToInt16Full);
/**
* 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.
*/
RTDECL(int16_t) RTStrToInt16(const char *pszValue)
{
int16_t i16;
int rc = RTStrToInt16Ex(pszValue, NULL, 0, &i16);
if (RT_SUCCESS(rc))
return i16;
return 0;
}
RT_EXPORT_SYMBOL(RTStrToInt16);
/**
* Converts a string representation of a number to a 8-bit signed number.
*
* @returns iprt status code.
* Warnings are used to indicate conversion 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)
*/
RTDECL(int) RTStrToInt8Ex(const char *pszValue, char **ppszNext, unsigned uBase, int8_t *pi8)
{
int64_t i64;
int rc = RTStrToInt64Ex(pszValue, ppszNext, uBase, &i64);
if (RT_SUCCESS(rc))
{
int8_t i8 = (int8_t)i64;
if (i64 != (int64_t)i8)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pi8)
*pi8 = (int8_t)i64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToInt8Ex);
/**
* 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 conversion 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)
*/
RTDECL(int) RTStrToInt8Full(const char *pszValue, unsigned uBase, int8_t *pi8)
{
int64_t i64;
int rc = RTStrToInt64Full(pszValue, uBase, &i64);
if (RT_SUCCESS(rc))
{
int8_t i8 = (int8_t)i64;
if (i64 != (int64_t)i8)
rc = VWRN_NUMBER_TOO_BIG;
}
if (pi8)
*pi8 = (int8_t)i64;
return rc;
}
RT_EXPORT_SYMBOL(RTStrToInt8Full);
/**
* 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.
*/
RTDECL(int8_t) RTStrToInt8(const char *pszValue)
{
int8_t i8;
int rc = RTStrToInt8Ex(pszValue, NULL, 0, &i8);
if (RT_SUCCESS(rc))
return i8;
return 0;
}
RT_EXPORT_SYMBOL(RTStrToInt8);
RTDECL(int) RTStrConvertHexBytes(char const *pszHex, void *pv, size_t cb, uint32_t fFlags)
{
size_t cbDst;
uint8_t *pbDst;
const char *pszSrc;
AssertPtrReturn(pszHex, VERR_INVALID_POINTER);
AssertReturn(!fFlags, VERR_INVALID_PARAMETER);
cbDst = cb;
pbDst = (uint8_t *)pv;
pszSrc = pszHex;
for (;;)
{
/* Pick the next two digit from the string. */
char ch = *pszSrc++;
unsigned char uchDigit1 = g_auchDigits[(unsigned char)ch];
unsigned char uchDigit2;
if (uchDigit1 >= 16)
{
if (!ch)
return cbDst == 0 ? VINF_SUCCESS : VERR_BUFFER_UNDERFLOW;
while (ch == ' ' || ch == '\t')
ch = *pszSrc++;
return ch ? VWRN_TRAILING_CHARS : VWRN_TRAILING_SPACES;
}
ch = *pszSrc++;
uchDigit2 = g_auchDigits[(unsigned char)ch];
if (uchDigit2 >= 16)
return VERR_UNEVEN_INPUT;
/* Add the byte to the output buffer. */
if (!cbDst)
return VERR_BUFFER_OVERFLOW;
cbDst--;
*pbDst++ = (uchDigit1 << 4) | uchDigit2;
}
}
RT_EXPORT_SYMBOL(RTStrConvertHexBytes);