Implement string to number conversion functions
All checks were successful
Builds / ExectOS (i686, release) (push) Successful in 29s
Builds / ExectOS (amd64, release) (push) Successful in 27s
Builds / ExectOS (i686, debug) (push) Successful in 41s
Builds / ExectOS (amd64, debug) (push) Successful in 43s

This commit is contained in:
2026-05-15 15:02:22 +02:00
parent 8ee97ac0ae
commit 29368a0dd8
5 changed files with 380 additions and 0 deletions

View File

@@ -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)

View File

@@ -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);

View File

@@ -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,

View File

@@ -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.
* *

View File

@@ -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.
* *