diff --git a/Jupiter/Functions.c b/Jupiter/Functions.c index b061156..11d881f 100644 --- a/Jupiter/Functions.c +++ b/Jupiter/Functions.c @@ -549,3 +549,186 @@ char *getTime() strftime(rtime, sizeof(rtime), "%a %b %d %H:%M:%S %Y %Z", localtime(&rawtime)); return rtime; } + + + +/** Character to integer conversion table */ + +const unsigned char baseTable[] = +{ + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 127, 127, 127, 127, 127, 127, + 127, 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, 127, 127, 127, 127, 127, + 127, 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, 127, 127, 127, 127, 127, + + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, + 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, 127, +}; + +/** Single character functions */ + +bool isBase(unsigned char c, int base) +{ + return baseTable[c] < base; +} + +bool isHex(unsigned char c) +{ + return isBase(c, 16); +} + +bool isDecimal(unsigned char c) +{ + return isBase(c, 10); +} + +int getBase(unsigned char c, int base) +{ + c = baseTable[c]; + if (c < base) return c; + return -1; +} + +/** Unsafe string converters */ + +int strtoi(const char *str, int base) +{ + while (isspace(*str)) str++; + return strtoi_nospace(str, base); +} + +unsigned int strtoui(const char *str, int base) +{ + while (isspace(*str)) str++; + return strtoi_nospace(str, base); +} + +int strtoi_nospace(const char *str, int base) +{ + if (*str != '-') return strtoui_nospace(str, base); + return -1 * strtoui_nospace(++str, base); +} + +unsigned int strtoui_nospace(const char *str, int base) +{ + unsigned int total = 0; + int tval; + if (*str == '-') return strtoi_nospace(str, base); + + if (*str == '+') str++; + + if (base == 0) // Guess a base. + { + if (*str == '0') + { + str++; + if (*str == 'x' || *str == 'X') + { + str++; + base = 16; + } + else base = 8; + } + else base = 10; + } + else if (base == 16) // check for optional preceeding hexadecimal prefix. + { + if (*str == '0') + { + str++; + if (*str == 'x' || *str == 'X') str++; + } + } + + while ((tval = getBase(*str, base)) != -1) + { + total = base * total + tval; + str++; + } + + return total; +} + +/** Safe string converters */ + +int strtoi_s(const char *str, size_t length, int base) +{ + while (isspace(*str)) + { + str++; + length--; + } + return strtoi_nospace_s(str, length, base); +} + +unsigned int strtoui_s(const char *str, size_t length, int base) +{ + while (isspace(*str)) + { + str++; + length--; + } + return strtoui_nospace_s(str, length, base); +} + +signed int strtoi_nospace_s(const char *str, size_t length, int base) +{ + if (length == 0) return 0; + if (*str != '-') return strtoui_nospace_s(str, length, base); + return -1 * strtoui_nospace_s(++str, --length, base); +} + +unsigned int strtoui_nospace_s(const char *str, size_t length, int base) +{ + unsigned int total = 0; + int tval; + if (length == 0) return total; + if (*str == '-') return strtoi_nospace(str, base); + + if (*str == '+') + { + if (--length == 0) return total; + str++; + } + + if (base == 0) // Guess a base. + { + if (*str == '0') + { + if (--length == 0) return total; + str++; + if (*str == 'x' || *str == 'X') + { + if (--length == 0) return total; + str++; + base = 16; + } + else base = 8; + } + else base = 10; + } + else if (base == 16) // check for optional preceeding hexadecimal prefix. + { + if (*str == '0') + { + if (--length == 0) return total; + str++; + if (*str == 'x' || *str == 'X') + { + if (--length == 0) return total; + str++; + } + } + } + + while ((tval = getBase(*str, base)) != -1) + { + total = base * total + tval; + if (--length == 0) return total; + str++; + } + + return total; +} diff --git a/Jupiter/Functions.h b/Jupiter/Functions.h index 49d0e1c..a7d0778 100644 --- a/Jupiter/Functions.h +++ b/Jupiter/Functions.h @@ -312,6 +312,85 @@ JUPITER_API uint32_t getPowerTwo32(uint32_t number); */ JUPITER_API uint64_t getPowerTwo64(uint64_t number); +/** +* @brief Checks if a character is a digit character of a specified radix. +* Note: The maximum base is 36 (0-9 and a-z) +* +* @param c Character to check. +* @return True if the character is a hexadecimal digit, false otherwise. +*/ +JUPITER_API bool isBase(unsigned char c, int base); + +/** +* @brief Checks if a character is a hexadecimal digit character. (base 16) +* +* @param c Character to check. +* @return True if the character is a hexadecimal digit, false otherwise. +*/ +JUPITER_API bool isHex(unsigned char c); + +/** +* @brief Checks if a character is a decimal digit character. (base 10) +* +* @param c Character to check. +* @return True if the character is a decimal digit, false otherwise. +*/ +JUPITER_API bool isDecimal(unsigned char c); + +/** +* @brief Fetches a character's represented integral value. +* Note: The maximum base is 36 (0-9 and a-z) +* +* @param c Character to fetch value of. +* @param base Base of the representation. +* @return A character's represented integral value on success, -1 otherwise. +*/ +JUPITER_API int getBase(unsigned char c, int base); + +/** +* @brief Interprets a string into an integer. +* +* @param str String to interpret. +* @param base Base of the string to interpret. 0 is acceptable. +* @return Interpretation of the string as an integer on success, 0 otherwise. +*/ +JUPITER_API int strtoi(const char *str, int base); +JUPITER_API unsigned int strtoui(const char *str, int base); + +/** +* @brief Interprets a string into an integer. +* Note: This function assumes no preceeding space characters exist. +* +* @param str String to interpret. +* @param base Base of the string to interpret. 0 is acceptable. +* @return Interpretation of the string as an integer on success, 0 otherwise. +*/ +JUPITER_API int strtoi_nospace(const char *str, int base); +JUPITER_API unsigned int strtoui_nospace(const char *str, int base); + +/** +* @brief Interprets a string into an integer. +* +* @param str String to interpret. +* @param length Length of str. +* @param base Base of the string to interpret. 0 is acceptable. +* @return Interpretation of the string as an integer on success, 0 otherwise. +*/ +JUPITER_API int strtoi_s(const char *str, size_t length, int base); +JUPITER_API unsigned int strtoui_s(const char *str, size_t length, int base); + +/** +* @brief Interprets a string into an integer. +* Note: This function assumes no preceeding space characters exist. +* +* @param str String to interpret. +* @param length Length of str. +* @param base Base of the string to interpret. 0 is acceptable. +* @return Interpretation of the string as an integer on success, 0 otherwise. +*/ +JUPITER_API int strtoi_nospace_s(const char *str, size_t length, int base); +JUPITER_API unsigned int strtoui_nospace_s(const char *str, size_t length, int base); + #if defined __cplusplus }