[string] add ParseDigit(), ParseHexDigit(), and other helper functions (#10282)

This commit adds a set of helper functions to parse a given digit or
hex digit character to its numeric value, or to check if a given
character is a digit, uppercase, or lowercase letter.
This commit is contained in:
Abtin Keshavarzian
2024-05-22 14:37:22 -07:00
committed by GitHub
parent 31ac6266fa
commit a57d927b0a
6 changed files with 162 additions and 50 deletions
+43 -4
View File
@@ -202,13 +202,15 @@ Error StringParseUint8(const char *&aString, uint8_t &aUint8, uint8_t aMaxValue)
Error error = kErrorParse;
const char *cur = aString;
uint16_t value = 0;
uint8_t digit;
for (; (*cur >= '0') && (*cur <= '9'); cur++)
while (ParseDigit(*cur, digit) == kErrorNone)
{
value *= 10;
value += static_cast<uint8_t>(*cur - '0');
value += digit;
VerifyOrExit(value <= aMaxValue, error = kErrorParse);
error = kErrorNone;
cur++;
}
aString = cur;
@@ -236,7 +238,7 @@ void StringConvertToUppercase(char *aString)
char ToLowercase(char aChar)
{
if ((aChar >= 'A') && (aChar <= 'Z'))
if (IsUppercase(aChar))
{
aChar += 'a' - 'A';
}
@@ -246,7 +248,7 @@ char ToLowercase(char aChar)
char ToUppercase(char aChar)
{
if ((aChar >= 'a') && (aChar <= 'z'))
if (IsLowercase(aChar))
{
aChar -= 'a' - 'A';
}
@@ -254,6 +256,43 @@ char ToUppercase(char aChar)
return aChar;
}
bool IsDigit(char aChar) { return ('0' <= aChar && aChar <= '9'); }
bool IsUppercase(char aChar) { return ('A' <= aChar && aChar <= 'Z'); }
bool IsLowercase(char aChar) { return ('a' <= aChar && aChar <= 'z'); }
Error ParseDigit(char aDigitChar, uint8_t &aValue)
{
Error error = kErrorNone;
VerifyOrExit(IsDigit(aDigitChar), error = kErrorInvalidArgs);
aValue = static_cast<uint8_t>(aDigitChar - '0');
exit:
return error;
}
Error ParseHexDigit(char aHexChar, uint8_t &aValue)
{
Error error = kErrorNone;
if (('A' <= aHexChar) && (aHexChar <= 'F'))
{
ExitNow(aValue = static_cast<uint8_t>(aHexChar - 'A' + 10));
}
if (('a' <= aHexChar) && (aHexChar <= 'f'))
{
ExitNow(aValue = static_cast<uint8_t>(aHexChar - 'a' + 10));
}
error = ParseDigit(aHexChar, aValue);
exit:
return error;
}
const char *ToYesNo(bool aBool)
{
static const char *const kYesNoStrings[] = {"no", "yes"};
+57
View File
@@ -282,6 +282,63 @@ char ToLowercase(char aChar);
*/
char ToUppercase(char aChar);
/**
* Checks whether a given character is an uppercase letter ('A'-'Z').
*
* @param[in] aChar The character to check.
*
* @retval TRUE @p aChar is an uppercase letter.
* @retval FALSE @p aChar is not an uppercase letter.
*
*/
bool IsUppercase(char aChar);
/**
* Checks whether a given character is a lowercase letter ('a'-'z').
*
* @param[in] aChar The character to check.
*
* @retval TRUE @p aChar is a lowercase letter.
* @retval FALSE @p aChar is not a lowercase letter.
*
*/
bool IsLowercase(char aChar);
/**
* Checks whether a given character is a digit character ('0'-'9').
*
* @param[in] aChar The character to check.
*
* @retval TRUE @p aChar is a digit character.
* @retval FALSE @p aChar is not a digit character.
*
*/
bool IsDigit(char aChar);
/**
* Parse a given digit character to its numeric value.
*
* @param[in] aDigitChar The digit character to parse.
* @param[out] aValue A reference to return the parsed value on success.
*
* @retval kErrorNone Successfully parsed the digit, @p aValue is updated.
* @retval kErrorInvalidArgs @p aDigitChar is not a valid digit character.
*
*/
Error ParseDigit(char aDigitChar, uint8_t &aValue);
/**
* Parse a given hex digit character ('0'-'9', 'A'-'F', or 'a'-'f') to its numeric value.
*
* @param[in] aHexChar The hex digit character to parse.
* @param[out] aValue A reference to return the parsed value on success.
*
* @retval kErrorNone Successfully parsed the digit, @p aValue is updated.
* @retval kErrorInvalidArgs @p aHexChar is not a valid hex digit character.
*
*/
Error ParseHexDigit(char aHexChar, uint8_t &aValue);
/**
* Coverts a boolean to "yes" or "no" string.
*
+1 -1
View File
@@ -95,7 +95,7 @@ bool JoinerPskd::IsPskdValid(const char *aPskdString)
{
char c = aPskdString[i];
VerifyOrExit(isdigit(c) || isupper(c));
VerifyOrExit(IsDigit(c) || IsUppercase(c));
VerifyOrExit(c != 'I' && c != 'O' && c != 'Q' && c != 'Z');
}
+1 -14
View File
@@ -586,22 +586,9 @@ Error Address::ParseFrom(const char *aString, char aTerminatorChar)
while (true)
{
char c = *aString;
uint8_t digit;
if (('A' <= c) && (c <= 'F'))
{
digit = static_cast<uint8_t>(c - 'A' + 10);
}
else if (('a' <= c) && (c <= 'f'))
{
digit = static_cast<uint8_t>(c - 'a' + 10);
}
else if (('0' <= c) && (c <= '9'))
{
digit = static_cast<uint8_t>(c - '0');
}
else
if (ParseHexDigit(*aString, digit) != kErrorNone)
{
break;
}
-31
View File
@@ -48,37 +48,6 @@ static bool IsSeparator(char aChar) { return (aChar == ' ') || (aChar == '\t') |
static bool IsEscapable(char aChar) { return IsSeparator(aChar) || (aChar == '\\'); }
static Error ParseDigit(char aDigitChar, uint8_t &aValue)
{
Error error = kErrorNone;
VerifyOrExit(('0' <= aDigitChar) && (aDigitChar <= '9'), error = kErrorInvalidArgs);
aValue = static_cast<uint8_t>(aDigitChar - '0');
exit:
return error;
}
static Error ParseHexDigit(char aHexChar, uint8_t &aValue)
{
Error error = kErrorNone;
if (('A' <= aHexChar) && (aHexChar <= 'F'))
{
ExitNow(aValue = static_cast<uint8_t>(aHexChar - 'A' + 10));
}
if (('a' <= aHexChar) && (aHexChar <= 'f'))
{
ExitNow(aValue = static_cast<uint8_t>(aHexChar - 'a' + 10));
}
error = ParseDigit(aHexChar, aValue);
exit:
return error;
}
Error ParseCmd(char *aCommandString, Arg aArgs[], uint8_t aArgsMaxLength)
{
Error error = kErrorNone;
+60
View File
@@ -337,6 +337,8 @@ void TestStringParseUint8(void)
{"0256", kErrorParse}, // Larger than max `uint8_t`
};
uint8_t digit;
printf("\nTest 11: TestStringParseUint8() function\n");
for (const TestCase &testCase : kTestCases)
@@ -363,6 +365,64 @@ void TestStringParseUint8(void)
}
}
for (char c = '0'; c <= '9'; c++)
{
VerifyOrQuit(IsDigit(c));
VerifyOrQuit(!IsUppercase(c));
VerifyOrQuit(!IsLowercase(c));
SuccessOrQuit(ParseDigit(c, digit));
VerifyOrQuit(digit == (c - '0'));
SuccessOrQuit(ParseHexDigit(c, digit));
VerifyOrQuit(digit == (c - '0'));
}
for (char c = 'A'; c <= 'Z'; c++)
{
VerifyOrQuit(!IsDigit(c));
VerifyOrQuit(IsUppercase(c));
VerifyOrQuit(!IsLowercase(c));
VerifyOrQuit(ParseDigit(c, digit) != kErrorNone);
if (c <= 'F')
{
SuccessOrQuit(ParseHexDigit(c, digit));
VerifyOrQuit(digit == (c - 'A' + 10));
}
else
{
VerifyOrQuit(ParseHexDigit(c, digit) != kErrorNone);
}
}
for (char c = 'a'; c <= 'z'; c++)
{
VerifyOrQuit(!IsDigit(c));
VerifyOrQuit(!IsUppercase(c));
VerifyOrQuit(IsLowercase(c));
VerifyOrQuit(ParseDigit(c, digit) != kErrorNone);
if (c <= 'f')
{
SuccessOrQuit(ParseHexDigit(c, digit));
VerifyOrQuit(digit == (c - 'a' + 10));
}
else
{
VerifyOrQuit(ParseHexDigit(c, digit) != kErrorNone);
}
}
VerifyOrQuit(!IsDigit(static_cast<char>('0' - 1)));
VerifyOrQuit(!IsDigit(static_cast<char>('9' + 1)));
VerifyOrQuit(!IsUppercase(static_cast<char>('A' - 1)));
VerifyOrQuit(!IsUppercase(static_cast<char>('Z' + 1)));
VerifyOrQuit(!IsLowercase(static_cast<char>('a' - 1)));
VerifyOrQuit(!IsLowercase(static_cast<char>('z' + 1)));
printf("\n\n -- PASS\n");
}