/* $Id$ */
/** @file
* IPRT - String To Number Conversion.
*/
/*
* Copyright (C) 2006-2012 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* you can redistribute it and/or modify it under the terms of the GNU
* 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.
*/
/*******************************************************************************
* Header Files *
*******************************************************************************/
#include <iprt/string.h>
#include "internal/iprt.h"
#include <iprt/assert.h>
#include <iprt/ctype.h> /* needed for RT_C_IS_DIGIT */
#include <iprt/err.h>
/*******************************************************************************
* 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 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);