Implement string to number conversion functions
This commit is contained in:
@@ -61,6 +61,8 @@
|
|||||||
#define STATUS_NO_MEMORY ((XTSTATUS) 0xC0000017L)
|
#define STATUS_NO_MEMORY ((XTSTATUS) 0xC0000017L)
|
||||||
#define STATUS_PORT_DISCONNECTED ((XTSTATUS) 0xC0000037L)
|
#define STATUS_PORT_DISCONNECTED ((XTSTATUS) 0xC0000037L)
|
||||||
#define STATUS_CRC_ERROR ((XTSTATUS) 0xC000003FL)
|
#define STATUS_CRC_ERROR ((XTSTATUS) 0xC000003FL)
|
||||||
|
#define STATUS_FLOAT_OVERFLOW ((XTSTATUS) 0xC0000091L)
|
||||||
|
#define STATUS_INTEGER_OVERFLOW ((XTSTATUS) 0xC0000095L)
|
||||||
#define STATUS_INSUFFICIENT_RESOURCES ((XTSTATUS) 0xC000009AL)
|
#define STATUS_INSUFFICIENT_RESOURCES ((XTSTATUS) 0xC000009AL)
|
||||||
#define STATUS_DEVICE_NOT_READY ((XTSTATUS) 0xC00000A3L)
|
#define STATUS_DEVICE_NOT_READY ((XTSTATUS) 0xC00000A3L)
|
||||||
#define STATUS_NOT_SUPPORTED ((XTSTATUS) 0xC00000BBL)
|
#define STATUS_NOT_SUPPORTED ((XTSTATUS) 0xC00000BBL)
|
||||||
|
|||||||
@@ -38,6 +38,9 @@ namespace RTL
|
|||||||
IN ULONG Length);
|
IN ULONG Length);
|
||||||
STATIC XTAPI SIZE_T StringLength(IN PCSTR String,
|
STATIC XTAPI SIZE_T StringLength(IN PCSTR String,
|
||||||
IN SIZE_T MaxLength);
|
IN SIZE_T MaxLength);
|
||||||
|
STATIC XTAPI XTSTATUS StringToNumber(IN PCSTR String,
|
||||||
|
IN ULONG Base,
|
||||||
|
OUT PULONG Value);
|
||||||
STATIC XTAPI SIZE_T StringToWideString(OUT PWCHAR Destination,
|
STATIC XTAPI SIZE_T StringToWideString(OUT PWCHAR Destination,
|
||||||
IN PCSTR *Source,
|
IN PCSTR *Source,
|
||||||
IN SIZE_T Length);
|
IN SIZE_T Length);
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ namespace RTL
|
|||||||
STATIC XTAPI PWCHAR TrimWideString(IN PWCHAR String);
|
STATIC XTAPI PWCHAR TrimWideString(IN PWCHAR String);
|
||||||
STATIC XTAPI SIZE_T WideStringLength(IN PCWSTR String,
|
STATIC XTAPI SIZE_T WideStringLength(IN PCWSTR String,
|
||||||
IN SIZE_T MaxLength);
|
IN SIZE_T MaxLength);
|
||||||
|
STATIC XTAPI XTSTATUS WideStringToNumber(IN PCWSTR String,
|
||||||
|
IN ULONG Base,
|
||||||
|
OUT PULONG Value);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
STATIC XTAPI XTSTATUS FormatArgumentSpecifier(IN PRTL_PRINT_CONTEXT Context,
|
STATIC XTAPI XTSTATUS FormatArgumentSpecifier(IN PRTL_PRINT_CONTEXT Context,
|
||||||
|
|||||||
@@ -427,6 +427,192 @@ RTL::String::StringLength(IN PCSTR String,
|
|||||||
return Length;
|
return Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a string to a number.
|
||||||
|
*
|
||||||
|
* @param String
|
||||||
|
* Supplies a pointer to the NULL-terminated string to convert.
|
||||||
|
*
|
||||||
|
* @param Base
|
||||||
|
* Supplies the optional numerical base for the conversion (2, 8, 10, or 16).
|
||||||
|
*
|
||||||
|
* @param Value
|
||||||
|
* Supplies a pointer to a variable that receives the converted numeric value.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
RTL::String::StringToNumber(IN PCSTR String,
|
||||||
|
IN ULONG Base,
|
||||||
|
OUT PULONG Value)
|
||||||
|
{
|
||||||
|
BOOLEAN NegativeValue;
|
||||||
|
ULONG Digit, Result;
|
||||||
|
|
||||||
|
/* Validate input parameters */
|
||||||
|
if(!String || !Value)
|
||||||
|
{
|
||||||
|
/* Invalid input parameters, return error code */
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize local variables */
|
||||||
|
NegativeValue = FALSE;
|
||||||
|
Result = 0;
|
||||||
|
|
||||||
|
/* Skip leading whitespaces and control characters */
|
||||||
|
while(*String != '\0' && *String <= ' ')
|
||||||
|
{
|
||||||
|
/* Advance to the next character */
|
||||||
|
String++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consume and record sign */
|
||||||
|
if(*String == '-')
|
||||||
|
{
|
||||||
|
/* Set negative value flag and advance to the next character */
|
||||||
|
NegativeValue = TRUE;
|
||||||
|
String++;
|
||||||
|
}
|
||||||
|
else if(*String == '+')
|
||||||
|
{
|
||||||
|
/* Advance to the next character */
|
||||||
|
String++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Autodetect and validate the base */
|
||||||
|
if(Base == 0)
|
||||||
|
{
|
||||||
|
/* Autodetect base based on prefix */
|
||||||
|
if(String[0] == '0')
|
||||||
|
{
|
||||||
|
/* Validate prefix */
|
||||||
|
if(String[1] == 'x' || String[1] == 'X')
|
||||||
|
{
|
||||||
|
/* Hexadecimal base */
|
||||||
|
Base = 16;
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else if(String[1] == 'o' || String[1] == 'O')
|
||||||
|
{
|
||||||
|
/* Octal base */
|
||||||
|
Base = 8;
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else if(String[1] == 'b' || String[1] == 'B')
|
||||||
|
{
|
||||||
|
/* Binary base */
|
||||||
|
Base = 2;
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Starts with 0 but no known prefix, treat as decimal */
|
||||||
|
Base = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Default to decimal base */
|
||||||
|
Base = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Validate explicitly provided base */
|
||||||
|
if(Base != 2 && Base != 8 && Base != 10 && Base != 16)
|
||||||
|
{
|
||||||
|
/* Invalid base, return error code */
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if number starts with 0 */
|
||||||
|
if(String[0] == '0')
|
||||||
|
{
|
||||||
|
/* Check for prefix */
|
||||||
|
if(Base == 16 && (String[1] == 'x' || String[1] == 'X'))
|
||||||
|
{
|
||||||
|
/* Skip hexadecimal prefix */
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else if(Base == 8 && (String[1] == 'o' || String[1] == 'O'))
|
||||||
|
{
|
||||||
|
/* Skip octal prefix */
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else if(Base == 2 && (String[1] == 'b' || String[1] == 'B'))
|
||||||
|
{
|
||||||
|
/* Skip binary prefix */
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse string character by character */
|
||||||
|
while(*String != '\0')
|
||||||
|
{
|
||||||
|
/* Convert character to numeric digit */
|
||||||
|
if(*String >= '0' && *String <= '9')
|
||||||
|
{
|
||||||
|
/* Convert decimal digit */
|
||||||
|
Digit = *String - '0';
|
||||||
|
}
|
||||||
|
else if(*String >= 'A' && *String <= 'F')
|
||||||
|
{
|
||||||
|
/* Convert hexadecimal digit */
|
||||||
|
Digit = *String - 'A' + 10;
|
||||||
|
}
|
||||||
|
else if(*String >= 'a' && *String <= 'f')
|
||||||
|
{
|
||||||
|
/* Convert hexadecimal digit */
|
||||||
|
Digit = *String - 'a' + 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid character for a number encountered, stop parsing */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if digit is valid for the current base */
|
||||||
|
if(Digit >= Base)
|
||||||
|
{
|
||||||
|
/* Digit out of range for this base, stop parsing */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for integer overflow */
|
||||||
|
if((Result > (MAXULONG / Base)) || ((Result * Base) > (MAXULONG - Digit)))
|
||||||
|
{
|
||||||
|
/* Integer overflow, return error code */
|
||||||
|
return STATUS_INTEGER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Accumulate result */
|
||||||
|
Result = (Result * Base) + Digit;
|
||||||
|
|
||||||
|
/* Advance to the next character */
|
||||||
|
String++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for negative value */
|
||||||
|
if(NegativeValue)
|
||||||
|
{
|
||||||
|
/* Apply sign and return the result */
|
||||||
|
*Value = (ULONG)(-(LONG)Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Return the result */
|
||||||
|
*Value = Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a multibyte character string to its wide character representation.
|
* Converts a multibyte character string to its wide character representation.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -1524,6 +1524,192 @@ RTL::WideString::WideStringLength(IN PCWSTR String,
|
|||||||
return Length;
|
return Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a wide string to a number.
|
||||||
|
*
|
||||||
|
* @param String
|
||||||
|
* Supplies a pointer to the NULL-terminated wide string to convert.
|
||||||
|
*
|
||||||
|
* @param Base
|
||||||
|
* Supplies the optional numerical base for the conversion (2, 8, 10, or 16).
|
||||||
|
*
|
||||||
|
* @param Value
|
||||||
|
* Supplies a pointer to a variable that receives the converted numeric value.
|
||||||
|
*
|
||||||
|
* @return This routine returns a status code.
|
||||||
|
*
|
||||||
|
* @since XT 1.0
|
||||||
|
*/
|
||||||
|
XTAPI
|
||||||
|
XTSTATUS
|
||||||
|
RTL::WideString::WideStringToNumber(IN PCWSTR String,
|
||||||
|
IN ULONG Base,
|
||||||
|
OUT PULONG Value)
|
||||||
|
{
|
||||||
|
BOOLEAN NegativeValue;
|
||||||
|
ULONG Digit, Result;
|
||||||
|
|
||||||
|
/* Validate input parameters */
|
||||||
|
if(!String || !Value)
|
||||||
|
{
|
||||||
|
/* Invalid input parameters, return error code */
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Initialize local variables */
|
||||||
|
NegativeValue = FALSE;
|
||||||
|
Result = 0;
|
||||||
|
|
||||||
|
/* Skip leading whitespaces and control characters */
|
||||||
|
while(*String != L'\0' && *String <= L' ')
|
||||||
|
{
|
||||||
|
/* Advance to the next character */
|
||||||
|
String++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Consume and record sign */
|
||||||
|
if(*String == L'-')
|
||||||
|
{
|
||||||
|
/* Set negative value flag and advance to the next character */
|
||||||
|
NegativeValue = TRUE;
|
||||||
|
String++;
|
||||||
|
}
|
||||||
|
else if(*String == L'+')
|
||||||
|
{
|
||||||
|
/* Advance to the next character */
|
||||||
|
String++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Autodetect and validate the base */
|
||||||
|
if(Base == 0)
|
||||||
|
{
|
||||||
|
/* Autodetect base based on prefix */
|
||||||
|
if(String[0] == L'0')
|
||||||
|
{
|
||||||
|
/* Validate prefix */
|
||||||
|
if(String[1] == L'x' || String[1] == L'X')
|
||||||
|
{
|
||||||
|
/* Hexadecimal base */
|
||||||
|
Base = 16;
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else if(String[1] == L'o' || String[1] == L'O')
|
||||||
|
{
|
||||||
|
/* Octal base */
|
||||||
|
Base = 8;
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else if(String[1] == L'b' || String[1] == L'B')
|
||||||
|
{
|
||||||
|
/* Binary base */
|
||||||
|
Base = 2;
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Starts with 0 but no known prefix, treat as decimal */
|
||||||
|
Base = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Default to decimal base */
|
||||||
|
Base = 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Validate explicitly provided base */
|
||||||
|
if(Base != 2 && Base != 8 && Base != 10 && Base != 16)
|
||||||
|
{
|
||||||
|
/* Invalid base, return error code */
|
||||||
|
return STATUS_INVALID_PARAMETER;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if number starts with 0 */
|
||||||
|
if(String[0] == L'0')
|
||||||
|
{
|
||||||
|
/* Check for prefix */
|
||||||
|
if(Base == 16 && (String[1] == L'x' || String[1] == L'X'))
|
||||||
|
{
|
||||||
|
/* Skip hexadecimal prefix */
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else if(Base == 8 && (String[1] == L'o' || String[1] == L'O'))
|
||||||
|
{
|
||||||
|
/* Skip octal prefix */
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
else if(Base == 2 && (String[1] == L'b' || String[1] == L'B'))
|
||||||
|
{
|
||||||
|
/* Skip binary prefix */
|
||||||
|
String += 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Parse string character by character */
|
||||||
|
while(*String != L'\0')
|
||||||
|
{
|
||||||
|
/* Convert wide character to numeric digit */
|
||||||
|
if(*String >= L'0' && *String <= L'9')
|
||||||
|
{
|
||||||
|
/* Convert decimal digit */
|
||||||
|
Digit = *String - L'0';
|
||||||
|
}
|
||||||
|
else if(*String >= L'A' && *String <= L'F')
|
||||||
|
{
|
||||||
|
/* Convert hexadecimal digit */
|
||||||
|
Digit = *String - L'A' + 10;
|
||||||
|
}
|
||||||
|
else if(*String >= L'a' && *String <= L'f')
|
||||||
|
{
|
||||||
|
/* Convert hexadecimal digit */
|
||||||
|
Digit = *String - L'a' + 10;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Invalid character for a number encountered, stop parsing */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check if digit is valid for the current base */
|
||||||
|
if(Digit >= Base)
|
||||||
|
{
|
||||||
|
/* Digit out of range for this base, stop parsing */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for integer overflow */
|
||||||
|
if((Result > (MAXULONG / Base)) || ((Result * Base) > (MAXULONG - Digit)))
|
||||||
|
{
|
||||||
|
/* Integer overflow, return error code */
|
||||||
|
return STATUS_INTEGER_OVERFLOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Accumulate result */
|
||||||
|
Result = (Result * Base) + Digit;
|
||||||
|
|
||||||
|
/* Advance to the next character */
|
||||||
|
String++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check for negative value */
|
||||||
|
if(NegativeValue)
|
||||||
|
{
|
||||||
|
/* Apply sign and return the result */
|
||||||
|
*Value = (ULONG)(-(LONG)Result);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* Return the result */
|
||||||
|
*Value = Result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Return success */
|
||||||
|
return STATUS_SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Writes a wide character to the destination provided by the print context.
|
* Writes a wide character to the destination provided by the print context.
|
||||||
*
|
*
|
||||||
|
|||||||
Reference in New Issue
Block a user