]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/Source/Reliance-Edge/tests/util/atoi.c
Update Reliance Edge fail safe file system to the latest version.
[freertos] / FreeRTOS-Plus / Source / Reliance-Edge / tests / util / atoi.c
index e4cd113a5272db925e066d88f17f45eee054f554..ec11e0a96406a41ec04bf135d19196a6eba254b7 100644 (file)
-/*             ----> DO NOT REMOVE THE FOLLOWING NOTICE <----\r
-\r
-                   Copyright (c) 2014-2015 Datalight, Inc.\r
-                       All Rights Reserved Worldwide.\r
-\r
-    This program is free software; you can redistribute it and/or modify\r
-    it under the terms of the GNU General Public License as published by\r
-    the Free Software Foundation; use version 2 of the License.\r
-\r
-    This program is distributed in the hope that it will be useful,\r
-    but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty\r
-    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
-    GNU General Public License for more details.\r
-\r
-    You should have received a copy of the GNU General Public License along\r
-    with this program; if not, write to the Free Software Foundation, Inc.,\r
-    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
-*/\r
-/*  Businesses and individuals that for commercial or other reasons cannot\r
-    comply with the terms of the GPLv2 license may obtain a commercial license\r
-    before incorporating Reliance Edge into proprietary software for\r
-    distribution in any form.  Visit http://www.datalight.com/reliance-edge for\r
-    more information.\r
-*/\r
-/** @file\r
-    @brief Implements utilities that convert strings to numbers.\r
-*/\r
-#include <redfs.h>\r
-#include <redtestutils.h>\r
-\r
-\r
-#define ISHEXDIGITU(c)  (((c) >= 'A') && ((c) <= 'F'))\r
-#define ISHEXDIGITL(c)  (((c) >= 'a') && ((c) <= 'f'))\r
-#define ISHEXDIGIT(c)   (ISHEXDIGITL(c) || ISHEXDIGITU(c))\r
-\r
-\r
-/** @brief Converts an ASCII number into an int32_t.\r
-\r
-    Converts all decimal digit numbers up to the end of the string or to the\r
-    first non-numerical character.\r
-\r
-    @note This function does *not* ignore leading white space.\r
-\r
-    @param pszNum   Pointer to a constant array of characters.\r
-\r
-    @return The integer represented in the string.\r
-*/\r
-int32_t RedAtoI(\r
-    const char *pszNum)\r
-{\r
-    int32_t     lValue = 0;\r
-    int32_t     lNegative = 1;\r
-    uint32_t    ulIdx = 0U;\r
-\r
-    if(pszNum[ulIdx] == '+')\r
-    {\r
-        ulIdx++;\r
-    }\r
-    else if(pszNum[ulIdx] == '-')\r
-    {\r
-        ulIdx++;\r
-        lNegative = -1;\r
-    }\r
-    else\r
-    {\r
-        /*  No sign, implicitly positive.\r
-        */\r
-    }\r
-\r
-    while(ISDIGIT(pszNum[ulIdx]))\r
-    {\r
-        lValue *= 10;\r
-        lValue += pszNum[ulIdx] - '0';\r
-        ulIdx++;\r
-    }\r
-\r
-    lValue *= lNegative;\r
-\r
-    return lValue;\r
-}\r
-\r
-\r
-/** @brief Convert a hexadecimal ASCII number into a uint32_t value.\r
-\r
-    The function processes all hex digits up to a NUL-terminator, or to the\r
-    first non-hex character.  Only hexadecimal digits are processed, so leading\r
-    white space, or a leading "0x" prefix are not allowed.\r
-\r
-    If pachNum points to an empty string (points to a NUL), this function will\r
-    return NULL, and the value at *pulNum will not be modified.\r
-\r
-    @note This function does not check for overflow.  If there are more\r
-          significant digits than can be represented in a uint32_t variable, the\r
-          output is unspecified.\r
-\r
-    @param pachNum  A pointer to a constant array of hex characters.\r
-    @param pulNum   A pointer to the location in which to store the uint32_t\r
-                    result.  Upon return, this value will be modified ONLY if\r
-                    the function succeeds and the returned pointer is valid (not\r
-                    NULL).\r
-\r
-    @return A pointer to the byte following the converted number or NULL to\r
-            indicate failure.\r
-*/\r
-const char *RedHtoUL(\r
-    const char *pszNum,\r
-    uint32_t   *pulNum)\r
-{\r
-    uint64_t    ullValue;\r
-    const char *pszReturn;\r
-\r
-    pszReturn = RedHtoULL(pszNum, &ullValue);\r
-    if(pszReturn != NULL)\r
-    {\r
-        if(ullValue < UINT32_MAX)\r
-        {\r
-            *pulNum = (uint32_t)ullValue;\r
-        }\r
-        else\r
-        {\r
-            pszReturn = NULL;\r
-        }\r
-    }\r
-\r
-    return pszReturn;\r
-}\r
-\r
-\r
-/** @brief Convert a hexadecimal ASCII number into a D_UINT64 value.\r
-\r
-    The function processes all hex digits up to a NUL-terminator, or to the\r
-    first non-hex character.  Only hexadecimal digits are processed, so leading\r
-    white space, or a leading "0x" prefix are not allowed.\r
-\r
-    If pachNum points to an empty string (points to a NUL), this function will\r
-    return NULL, and the value at *pulNum will not be modified.\r
-\r
-    @note This function does not check for overflow.  If there are more\r
-          significant digits than can be represented in a uint64_t variable, the\r
-          output is unspecified.\r
-\r
-    @param pszNum   A pointer to a constant array of hex characters.\r
-    @param pullNum  A pointer to the location in which to store the uint64_t\r
-                    result.  Upon return, this value will be modified ONLY if\r
-                    the function succeeds and the returned pointer is valid (not\r
-                    NULL).\r
-\r
-    @return A pointer to the byte following the converted number, or NULL to\r
-            indicate failure.\r
-*/\r
-const char *RedHtoULL(\r
-    const char *pszNum,\r
-    uint64_t   *pullNum)\r
-{\r
-    uint64_t    ullValue = 0U;\r
-    const char *pszReturn = NULL;\r
-    uint32_t    ulIdx = 0U;\r
-\r
-    REDASSERT(pszNum != NULL);\r
-    REDASSERT(pullNum != NULL);\r
-\r
-    while(pszNum[ulIdx] != '\0')\r
-    {\r
-        char cDigit = pszNum[ulIdx];\r
-\r
-        if(ISDIGIT(cDigit))\r
-        {\r
-            cDigit -= '0';\r
-        }\r
-        else if(ISHEXDIGITU(cDigit))\r
-        {\r
-            cDigit -= ('A' - 10);\r
-        }\r
-        else if(ISHEXDIGITL(cDigit))\r
-        {\r
-            cDigit -= ('a' - 10);\r
-        }\r
-        else\r
-        {\r
-            break;\r
-        }\r
-\r
-        REDASSERT((ullValue & UINT64_SUFFIX(0xF000000000000000)) == 0U);\r
-\r
-        ullValue <<= 4U;\r
-        ullValue += cDigit;\r
-\r
-        ulIdx++;\r
-        pszReturn = &pszNum[ulIdx];\r
-    }\r
-\r
-    /*  Modify the number returned only if we found one or more valid hex\r
-        digits.\r
-    */\r
-    if(pszReturn != NULL)\r
-    {\r
-        *pullNum = ullValue;\r
-    }\r
-\r
-    return pszReturn;\r
-}\r
-\r
-\r
-/** @brief Convert the ASCII number to a uint32_t  value.\r
-\r
-    The number may be hex or decimal.  Hex numbers must be prefixed by '0x', and\r
-    they may be upper or lower case.  The conversion process will stop with the\r
-    first non hex or decimal digit.\r
-\r
-    If the number is negative (the first character is a '-' sign), the value\r
-    will be range checked and returned as the equivalent unsigned value.\r
-\r
-    @note   This function will NOT fail for numbers which exceed the size of a\r
-            uint32_t value.\r
-\r
-    @param pszNum   A pointer to the ASCII number to convert\r
-    @param pulNum   A pointer to the uint32_t location to store the result.\r
-                    This value will be modified on return only if the function\r
-                    succeeds and the returned pointer is valid (not NULL).\r
-\r
-    @return A pointer to the byte following the converted number, or NULL to\r
-            indicate failure.\r
-*/\r
-const char *RedNtoUL(\r
-    const char *pszNum,\r
-    uint32_t   *pulNum)\r
-{\r
-    bool        fNegative = false;\r
-    uint32_t    ulIdx = 0U;\r
-    const char *pszReturn;\r
-\r
-    REDASSERT(pszNum != NULL);\r
-    REDASSERT(pulNum != NULL);\r
-\r
-    if(pszNum[ulIdx] == '-')\r
-    {\r
-        fNegative = true;\r
-        ulIdx++;\r
-    }\r
-\r
-    /*  Hex numbers must be prefixed with '0x'.\r
-    */\r
-    if((pszNum[ulIdx] == '0') && ((pszNum[ulIdx + 1U] == 'x') || (pszNum[ulIdx + 1U] == 'X')))\r
-    {\r
-        ulIdx += 2U;\r
-\r
-        if(ISDIGIT(pszNum[ulIdx]) || ISHEXDIGIT(pszNum[ulIdx]))\r
-        {\r
-            pszReturn = RedHtoUL(&pszNum[ulIdx], pulNum);\r
-        }\r
-        else\r
-        {\r
-            pszReturn = NULL;\r
-        }\r
-    }\r
-    else if(ISDIGIT(pszNum[ulIdx]))\r
-    {\r
-        uint32_t ulTemp;\r
-\r
-        ulTemp = RedAtoI(&pszNum[ulIdx]);\r
-\r
-        while(ISDIGIT(pszNum[ulIdx]))\r
-        {\r
-            ulIdx++;\r
-        }\r
-\r
-        if(fNegative)\r
-        {\r
-            /*  Fail if the number is out of range.\r
-            */\r
-            if(ulTemp > INT32_MAX)\r
-            {\r
-                pszReturn = NULL;\r
-            }\r
-            else\r
-            {\r
-                *pulNum = -((int32_t)ulTemp);\r
-                pszReturn = &pszNum[ulIdx];\r
-            }\r
-        }\r
-        else\r
-        {\r
-            *pulNum = ulTemp;\r
-            pszReturn = &pszNum[ulIdx];\r
-        }\r
-    }\r
-    else\r
-    {\r
-        /*  Return an error if there is not at least one hex or decimal digit.\r
-        */\r
-        pszReturn = NULL;\r
-    }\r
-\r
-    return pszReturn;\r
-}\r
-\r
-\r
-/** @brief Convert the ASCII number pointed to by pachNum to a uint64_t value.\r
-\r
-    The number may be hex or decimal.  Hex numbers must be prefixed by '0x', and\r
-    they may be upper or lower case.  The conversion process will stop with the\r
-    first non hex or decimal digit.\r
-\r
-    If the number is negative (the first character is a '-' sign), the value\r
-    will be range checked and returned as the equivalent unsigned value.\r
-\r
-    @param pszNum   A pointer to the ASCII number to convert.\r
-    @param pullNum  A pointer to the uint64_t location to store the result.\r
-                    This value will be modified on return only if the function\r
-                    succeeds and the returned pointer is valid (not NULL).\r
-\r
-    @return A pointer to the byte following the converted number, or NULL to\r
-            indicate failure.\r
-*/\r
-const char *RedNtoULL(\r
-    const char *pszNum,\r
-    uint64_t   *pullNum)\r
-{\r
-    bool        fNegative = false;\r
-    uint32_t    ulIdx = 0U;\r
-    const char *pszReturn;\r
-\r
-    REDASSERT(pszNum != NULL);\r
-    REDASSERT(pullNum != NULL);\r
-\r
-    if(pszNum[ulIdx] == '-')\r
-    {\r
-        fNegative = true;\r
-        ulIdx++;\r
-    }\r
-\r
-    /*  Hex numbers must be prefixed with '0x'.\r
-    */\r
-    if((pszNum[ulIdx] == '0') && ((pszNum[ulIdx + 1U] == 'x') || (pszNum[ulIdx + 1U] == 'X')))\r
-    {\r
-        ulIdx += 2U;\r
-\r
-        if(ISDIGIT(pszNum[ulIdx]) || ISHEXDIGIT(pszNum[ulIdx]))\r
-        {\r
-            pszReturn = RedHtoULL(&pszNum[ulIdx], pullNum);\r
-        }\r
-        else\r
-        {\r
-            pszReturn = NULL;\r
-        }\r
-    }\r
-    else if(ISDIGIT(pszNum[ulIdx]))\r
-    {\r
-        uint64_t ullTemp = 0U;\r
-\r
-        while(ISDIGIT(pszNum[ulIdx]))\r
-        {\r
-            ullTemp *= 10U;\r
-            ullTemp += pszNum[ulIdx] - '0';\r
-            ulIdx++;\r
-        }\r
-\r
-        if(fNegative)\r
-        {\r
-            /*  Fail if the number is out of range.\r
-            */\r
-            if(ullTemp > INT64_MAX)\r
-            {\r
-                pszReturn = NULL;\r
-            }\r
-            else\r
-            {\r
-                *pullNum = (uint64_t)(-((int64_t)ullTemp));\r
-                pszReturn = &pszNum[ulIdx];\r
-            }\r
-        }\r
-        else\r
-        {\r
-            *pullNum = ullTemp;\r
-            pszReturn = &pszNum[ulIdx];\r
-        }\r
-    }\r
-    else\r
-    {\r
-        /*  Return an error if there is not at least one hex or decimal digit.\r
-        */\r
-        pszReturn = NULL;\r
-    }\r
-\r
-    return pszReturn;\r
-}\r
-\r
-\r
-/** @brief Convert an ASCII hex or decimal number, which may may have a "B",\r
-           "KB", or "MB" suffix (case insensitive), to a binary value.\r
-\r
-    Hex numbers must be prefixed with "0x".\r
-\r
-    @note If there is no postfix, KB is assumed!\r
-\r
-    May fail due to bad formatting or overflow.\r
-\r
-    @param pszNum       A pointer to the ASCII number to convert.\r
-    @param pulResult    A pointer to a uint32_t in which to place the result.\r
-\r
-    @return A pointer to the byte following the string, or NULL to indicate an\r
-            error.  In the event of an error, *pulResult will not be modified.\r
-*/\r
-const char *RedSizeToUL(\r
-    const char *pszNum,\r
-    uint32_t   *pulResult)\r
-{\r
-    uint32_t    ulResult;\r
-    const char *pszSuffix;\r
-    const char *pszReturn;\r
-    uint32_t    ulIdx = 0U;\r
-\r
-    REDASSERT(pszNum != NULL);\r
-    REDASSERT(pulResult != NULL);\r
-\r
-    /*  Do the basic hex/decimal conversion\r
-    */\r
-    pszSuffix = RedNtoUL(pszNum, &ulResult);\r
-    if(pszSuffix != NULL)\r
-    {\r
-        if((pszSuffix[ulIdx] == 'B') || (pszSuffix[ulIdx] == 'b'))\r
-        {\r
-            ulIdx++;\r
-            pszReturn = &pszSuffix[ulIdx];\r
-        }\r
-        else if(    ((pszSuffix[ulIdx] == 'M') || (pszSuffix[ulIdx] == 'm'))\r
-                 && ((pszSuffix[ulIdx + 1U] == 'B') || (pszSuffix[ulIdx + 1U] == 'b')))\r
-        {\r
-            ulIdx += 2U;\r
-\r
-            if(ulResult > (UINT32_MAX / (1024U * 1024U)))\r
-            {\r
-                pszReturn = NULL;\r
-            }\r
-            else\r
-            {\r
-                ulResult *= 1024U * 1024U;\r
-                pszReturn = &pszSuffix[ulIdx];\r
-            }\r
-        }\r
-        else\r
-        {\r
-            /*  The number is either postfixed with "KB" or something\r
-                else (we don't care), but we must increment the pointer\r
-                if it is something recognize.\r
-            */\r
-            if(    ((pszSuffix[ulIdx] == 'K') || (pszSuffix[ulIdx] == 'k'))\r
-                && ((pszSuffix[ulIdx + 1U] == 'B') || (pszSuffix[ulIdx + 1U] == 'b')))\r
-            {\r
-                ulIdx += 2U;\r
-            }\r
-\r
-            /*  "B" or "MB" were not specified, so it must be "KB"\r
-            */\r
-            if(ulResult > (UINT32_MAX / 1024U))\r
-            {\r
-                pszReturn = NULL;\r
-            }\r
-            else\r
-            {\r
-                ulResult *= 1024UL;\r
-                pszReturn = &pszSuffix[ulIdx];\r
-            }\r
-        }\r
-\r
-        if(pszReturn != NULL)\r
-        {\r
-            *pulResult = ulResult;\r
-        }\r
-    }\r
-    else\r
-    {\r
-        pszReturn = NULL;\r
-    }\r
-\r
-    return pszReturn;\r
-}\r
-\r
+/*             ----> DO NOT REMOVE THE FOLLOWING NOTICE <----
+
+                   Copyright (c) 2014-2015 Datalight, Inc.
+                       All Rights Reserved Worldwide.
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; use version 2 of the License.
+
+    This program is distributed in the hope that it will be useful,
+    but "AS-IS," WITHOUT ANY WARRANTY; without even the implied warranty
+    of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License along
+    with this program; if not, write to the Free Software Foundation, Inc.,
+    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+/*  Businesses and individuals that for commercial or other reasons cannot
+    comply with the terms of the GPLv2 license may obtain a commercial license
+    before incorporating Reliance Edge into proprietary software for
+    distribution in any form.  Visit http://www.datalight.com/reliance-edge for
+    more information.
+*/
+/** @file
+    @brief Implements utilities that convert strings to numbers.
+*/
+#include <redfs.h>
+#include <redtestutils.h>
+
+
+#define ISHEXDIGITU(c)  (((c) >= 'A') && ((c) <= 'F'))
+#define ISHEXDIGITL(c)  (((c) >= 'a') && ((c) <= 'f'))
+#define ISHEXDIGIT(c)   (ISHEXDIGITL(c) || ISHEXDIGITU(c))
+
+
+/** @brief Converts an ASCII number into an int32_t.
+
+    Converts all decimal digit numbers up to the end of the string or to the
+    first non-numerical character.
+
+    @note This function does *not* ignore leading white space.
+
+    @param pszNum   Pointer to a constant array of characters.
+
+    @return The integer represented in the string.
+*/
+int32_t RedAtoI(
+    const char *pszNum)
+{
+    int32_t     lValue = 0;
+    int32_t     lNegative = 1;
+    uint32_t    ulIdx = 0U;
+
+    if(pszNum[ulIdx] == '+')
+    {
+        ulIdx++;
+    }
+    else if(pszNum[ulIdx] == '-')
+    {
+        ulIdx++;
+        lNegative = -1;
+    }
+    else
+    {
+        /*  No sign, implicitly positive.
+        */
+    }
+
+    while(ISDIGIT(pszNum[ulIdx]))
+    {
+        lValue *= 10;
+        lValue += pszNum[ulIdx] - '0';
+        ulIdx++;
+    }
+
+    lValue *= lNegative;
+
+    return lValue;
+}
+
+
+/** @brief Convert a hexadecimal ASCII number into a uint32_t value.
+
+    The function processes all hex digits up to a NUL-terminator, or to the
+    first non-hex character.  Only hexadecimal digits are processed, so leading
+    white space, or a leading "0x" prefix are not allowed.
+
+    If pachNum points to an empty string (points to a NUL), this function will
+    return NULL, and the value at *pulNum will not be modified.
+
+    @note This function does not check for overflow.  If there are more
+          significant digits than can be represented in a uint32_t variable, the
+          output is unspecified.
+
+    @param pszNum   A pointer to a constant array of hex characters.
+    @param pulNum   A pointer to the location in which to store the uint32_t
+                    result.  Upon return, this value will be modified ONLY if
+                    the function succeeds and the returned pointer is valid (not
+                    NULL).
+
+    @return A pointer to the byte following the converted number or NULL to
+            indicate failure.
+*/
+const char *RedHtoUL(
+    const char *pszNum,
+    uint32_t   *pulNum)
+{
+    uint64_t    ullValue;
+    const char *pszReturn;
+
+    pszReturn = RedHtoULL(pszNum, &ullValue);
+    if(pszReturn != NULL)
+    {
+        if(ullValue < UINT32_MAX)
+        {
+            *pulNum = (uint32_t)ullValue;
+        }
+        else
+        {
+            pszReturn = NULL;
+        }
+    }
+
+    return pszReturn;
+}
+
+
+/** @brief Convert a hexadecimal ASCII number into a D_UINT64 value.
+
+    The function processes all hex digits up to a NUL-terminator, or to the
+    first non-hex character.  Only hexadecimal digits are processed, so leading
+    white space, or a leading "0x" prefix are not allowed.
+
+    If pachNum points to an empty string (points to a NUL), this function will
+    return NULL, and the value at *pulNum will not be modified.
+
+    @note This function does not check for overflow.  If there are more
+          significant digits than can be represented in a uint64_t variable, the
+          output is unspecified.
+
+    @param pszNum   A pointer to a constant array of hex characters.
+    @param pullNum  A pointer to the location in which to store the uint64_t
+                    result.  Upon return, this value will be modified ONLY if
+                    the function succeeds and the returned pointer is valid (not
+                    NULL).
+
+    @return A pointer to the byte following the converted number, or NULL to
+            indicate failure.
+*/
+const char *RedHtoULL(
+    const char *pszNum,
+    uint64_t   *pullNum)
+{
+    uint64_t    ullValue = 0U;
+    const char *pszReturn = NULL;
+    uint32_t    ulIdx = 0U;
+
+    REDASSERT(pszNum != NULL);
+    REDASSERT(pullNum != NULL);
+
+    while(pszNum[ulIdx] != '\0')
+    {
+        char cDigit = pszNum[ulIdx];
+
+        if(ISDIGIT(cDigit))
+        {
+            cDigit -= '0';
+        }
+        else if(ISHEXDIGITU(cDigit))
+        {
+            cDigit -= ('A' - 10);
+        }
+        else if(ISHEXDIGITL(cDigit))
+        {
+            cDigit -= ('a' - 10);
+        }
+        else
+        {
+            break;
+        }
+
+        REDASSERT((ullValue & UINT64_SUFFIX(0xF000000000000000)) == 0U);
+
+        ullValue <<= 4U;
+        ullValue += cDigit;
+
+        ulIdx++;
+        pszReturn = &pszNum[ulIdx];
+    }
+
+    /*  Modify the number returned only if we found one or more valid hex
+        digits.
+    */
+    if(pszReturn != NULL)
+    {
+        *pullNum = ullValue;
+    }
+
+    return pszReturn;
+}
+
+
+/** @brief Convert the ASCII number to a uint32_t  value.
+
+    The number may be hex or decimal.  Hex numbers must be prefixed by '0x', and
+    they may be upper or lower case.  The conversion process will stop with the
+    first non hex or decimal digit.
+
+    If the number is negative (the first character is a '-' sign), the value
+    will be range checked and returned as the equivalent unsigned value.
+
+    @note   This function will NOT fail for numbers which exceed the size of a
+            uint32_t value.
+
+    @param pszNum   A pointer to the ASCII number to convert
+    @param pulNum   A pointer to the uint32_t location to store the result.
+                    This value will be modified on return only if the function
+                    succeeds and the returned pointer is valid (not NULL).
+
+    @return A pointer to the byte following the converted number, or NULL to
+            indicate failure.
+*/
+const char *RedNtoUL(
+    const char *pszNum,
+    uint32_t   *pulNum)
+{
+    bool        fNegative = false;
+    uint32_t    ulIdx = 0U;
+    const char *pszReturn;
+
+    REDASSERT(pszNum != NULL);
+    REDASSERT(pulNum != NULL);
+
+    if(pszNum[ulIdx] == '-')
+    {
+        fNegative = true;
+        ulIdx++;
+    }
+
+    /*  Hex numbers must be prefixed with '0x'.
+    */
+    if((pszNum[ulIdx] == '0') && ((pszNum[ulIdx + 1U] == 'x') || (pszNum[ulIdx + 1U] == 'X')))
+    {
+        ulIdx += 2U;
+
+        if(ISDIGIT(pszNum[ulIdx]) || ISHEXDIGIT(pszNum[ulIdx]))
+        {
+            pszReturn = RedHtoUL(&pszNum[ulIdx], pulNum);
+        }
+        else
+        {
+            pszReturn = NULL;
+        }
+    }
+    else if(ISDIGIT(pszNum[ulIdx]))
+    {
+        uint32_t ulTemp;
+
+        ulTemp = RedAtoI(&pszNum[ulIdx]);
+
+        while(ISDIGIT(pszNum[ulIdx]))
+        {
+            ulIdx++;
+        }
+
+        if(fNegative)
+        {
+            /*  Fail if the number is out of range.
+            */
+            if(ulTemp > INT32_MAX)
+            {
+                pszReturn = NULL;
+            }
+            else
+            {
+                *pulNum = -((int32_t)ulTemp);
+                pszReturn = &pszNum[ulIdx];
+            }
+        }
+        else
+        {
+            *pulNum = ulTemp;
+            pszReturn = &pszNum[ulIdx];
+        }
+    }
+    else
+    {
+        /*  Return an error if there is not at least one hex or decimal digit.
+        */
+        pszReturn = NULL;
+    }
+
+    return pszReturn;
+}
+
+
+/** @brief Convert the ASCII number pointed to by pachNum to a uint64_t value.
+
+    The number may be hex or decimal.  Hex numbers must be prefixed by '0x', and
+    they may be upper or lower case.  The conversion process will stop with the
+    first non hex or decimal digit.
+
+    If the number is negative (the first character is a '-' sign), the value
+    will be range checked and returned as the equivalent unsigned value.
+
+    @param pszNum   A pointer to the ASCII number to convert.
+    @param pullNum  A pointer to the uint64_t location to store the result.
+                    This value will be modified on return only if the function
+                    succeeds and the returned pointer is valid (not NULL).
+
+    @return A pointer to the byte following the converted number, or NULL to
+            indicate failure.
+*/
+const char *RedNtoULL(
+    const char *pszNum,
+    uint64_t   *pullNum)
+{
+    bool        fNegative = false;
+    uint32_t    ulIdx = 0U;
+    const char *pszReturn;
+
+    REDASSERT(pszNum != NULL);
+    REDASSERT(pullNum != NULL);
+
+    if(pszNum[ulIdx] == '-')
+    {
+        fNegative = true;
+        ulIdx++;
+    }
+
+    /*  Hex numbers must be prefixed with '0x'.
+    */
+    if((pszNum[ulIdx] == '0') && ((pszNum[ulIdx + 1U] == 'x') || (pszNum[ulIdx + 1U] == 'X')))
+    {
+        ulIdx += 2U;
+
+        if(ISDIGIT(pszNum[ulIdx]) || ISHEXDIGIT(pszNum[ulIdx]))
+        {
+            pszReturn = RedHtoULL(&pszNum[ulIdx], pullNum);
+        }
+        else
+        {
+            pszReturn = NULL;
+        }
+    }
+    else if(ISDIGIT(pszNum[ulIdx]))
+    {
+        uint64_t ullTemp = 0U;
+
+        while(ISDIGIT(pszNum[ulIdx]))
+        {
+            ullTemp *= 10U;
+            ullTemp += pszNum[ulIdx] - '0';
+            ulIdx++;
+        }
+
+        if(fNegative)
+        {
+            /*  Fail if the number is out of range.
+            */
+            if(ullTemp > INT64_MAX)
+            {
+                pszReturn = NULL;
+            }
+            else
+            {
+                *pullNum = (uint64_t)(-((int64_t)ullTemp));
+                pszReturn = &pszNum[ulIdx];
+            }
+        }
+        else
+        {
+            *pullNum = ullTemp;
+            pszReturn = &pszNum[ulIdx];
+        }
+    }
+    else
+    {
+        /*  Return an error if there is not at least one hex or decimal digit.
+        */
+        pszReturn = NULL;
+    }
+
+    return pszReturn;
+}
+
+
+/** @brief Convert an ASCII hex or decimal number, which may may have a "B",
+           "KB", or "MB" suffix (case insensitive), to a binary value.
+
+    Hex numbers must be prefixed with "0x".
+
+    @note If there is no postfix, KB is assumed!
+
+    May fail due to bad formatting or overflow.
+
+    @param pszNum       A pointer to the ASCII number to convert.
+    @param pulResult    A pointer to a uint32_t in which to place the result.
+
+    @return A pointer to the byte following the string, or NULL to indicate an
+            error.  In the event of an error, *pulResult will not be modified.
+*/
+const char *RedSizeToUL(
+    const char *pszNum,
+    uint32_t   *pulResult)
+{
+    uint32_t    ulResult;
+    const char *pszSuffix;
+    const char *pszReturn;
+    uint32_t    ulIdx = 0U;
+
+    REDASSERT(pszNum != NULL);
+    REDASSERT(pulResult != NULL);
+
+    /*  Do the basic hex/decimal conversion
+    */
+    pszSuffix = RedNtoUL(pszNum, &ulResult);
+    if(pszSuffix != NULL)
+    {
+        if((pszSuffix[ulIdx] == 'B') || (pszSuffix[ulIdx] == 'b'))
+        {
+            ulIdx++;
+            pszReturn = &pszSuffix[ulIdx];
+        }
+        else if(    ((pszSuffix[ulIdx] == 'M') || (pszSuffix[ulIdx] == 'm'))
+                 && ((pszSuffix[ulIdx + 1U] == 'B') || (pszSuffix[ulIdx + 1U] == 'b')))
+        {
+            ulIdx += 2U;
+
+            if(ulResult > (UINT32_MAX / (1024U * 1024U)))
+            {
+                pszReturn = NULL;
+            }
+            else
+            {
+                ulResult *= 1024U * 1024U;
+                pszReturn = &pszSuffix[ulIdx];
+            }
+        }
+        else
+        {
+            /*  The number is either postfixed with "KB" or something
+                else (we don't care), but we must increment the pointer
+                if it is something recognize.
+            */
+            if(    ((pszSuffix[ulIdx] == 'K') || (pszSuffix[ulIdx] == 'k'))
+                && ((pszSuffix[ulIdx + 1U] == 'B') || (pszSuffix[ulIdx + 1U] == 'b')))
+            {
+                ulIdx += 2U;
+            }
+
+            /*  "B" or "MB" were not specified, so it must be "KB"
+            */
+            if(ulResult > (UINT32_MAX / 1024U))
+            {
+                pszReturn = NULL;
+            }
+            else
+            {
+                ulResult *= 1024UL;
+                pszReturn = &pszSuffix[ulIdx];
+            }
+        }
+
+        if(pszReturn != NULL)
+        {
+            *pulResult = ulResult;
+        }
+    }
+    else
+    {
+        pszReturn = NULL;
+    }
+
+    return pszReturn;
+}
+