From d2d7fac4df00b0d62a4a77a056e9f2c6f666f0f3 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 20 Mar 2016 12:56:07 -0400 Subject: [PATCH] Lots of CString clean up; attempt #1 at implementing int to string conversion Long (64-bit) ints are hard to do on 32-bit... --- src/kstd/CString.cc | 151 +++++++++++++++++++++++++++++++++++++++++--- src/kstd/CString.hh | 34 ++++++++-- 2 files changed, 169 insertions(+), 16 deletions(-) diff --git a/src/kstd/CString.cc b/src/kstd/CString.cc index f5e0f35..7f66224 100644 --- a/src/kstd/CString.cc +++ b/src/kstd/CString.cc @@ -13,10 +13,11 @@ namespace kstd { namespace CString { usize -length(char* str) +length(const char* str, + usize max) { usize i; - for (i = 0; str[i] != '\0'; i++); + for (i = 0; str[i] != '\0' && i < max; i++); return i; } @@ -24,9 +25,10 @@ length(char* str) char* copy(char* dst, const char* src, - usize length) + usize max) { - for (usize i = 0; i < length; i++) { + usize len = length(src, max); + for (usize i = 0; i < len; i++) { dst[i] = src[i]; if (src[i] == '\0') { break; @@ -36,8 +38,25 @@ copy(char* dst, } +char* +reverse(char* str, + usize max) +{ + max = length(str, max); + char* p = str; + char* t = str + max - 1; + char c; + while (t > p) { + c = *p; + *p++ = *t; + *t-- = c; + } + return str; +} + + void -uppercase(char *str) +uppercase(char* str) { for (char *p = str; *p != '\0'; p++) { if (Char::isLower(*p)) { @@ -50,12 +69,124 @@ uppercase(char *str) * Converters */ -char* -fromInteger(int value, - char* str, - usize length) +/** + * Converts `value` to an un-reversed CString without a null terminator. It is + * expected that callers of this function will append a null terminator and + * reverse `str` at the appropriate time. + * + * @return A pointer to the character *after* all converted characters, such + * that `p - buffer` is the number of characters converted. + */ +static usize +_doConvertFromInteger(u32 value, + char* buffer, + usize length, + u8 base, + bool capitalized) { - return 0; + char* p = buffer; + int place; + do { + if (usize(p - buffer) >= length) { + break; + } + place = value % base; + value /= base; + *p++ = (place < 10) ? place + '0' : (place - 10) + (capitalized ? 'A' : 'a'); + } while (value != 0); + + return p - buffer; +} + +char* +fromInteger(i32 value, + char* buffer, + usize length, + u8 base, + bool capitalized) +{ + const bool negative = base == 10 && value < 0; + if (negative) { + value *= -1; + } + + usize convertedLength = _doConvertFromInteger(u32(value), buffer, length, base, capitalized); + + if (convertedLength < length && negative) { + buffer[convertedLength++] = '-'; + } + if (convertedLength < length) { + buffer[convertedLength] = '\0'; + } + + reverse(buffer, convertedLength); + + return buffer; +} + + +char* +fromUnsignedInteger(u32 value, + char* buffer, + usize length, + u8 base, + bool capitalized) +{ + usize convertedLength = _doConvertFromInteger(u32(value), buffer, length, base, capitalized); + if (convertedLength < length) { + buffer[convertedLength] = '\0'; + } + reverse(buffer, convertedLength); + return buffer; +} + + +char* +fromLongInteger(i64 value, + char* buffer, + usize length, + u8 base, + bool capitalized) +{ + const bool negative = base == 10 && value < 0; + if (negative) { + value *= -1; + } + + // Do large ints in two passes. First do the high-order bits, then the lower order bits. + usize convertedLength; + convertedLength = _doConvertFromInteger(u32(value >> 32), buffer, length, base, capitalized); + convertedLength += _doConvertFromInteger(u32(value), &buffer[convertedLength], length - convertedLength, base, capitalized); + + if (convertedLength < length && negative) { + buffer[convertedLength++] = '-'; + } + if (convertedLength < length) { + buffer[convertedLength] = '\0'; + } + + reverse(buffer, convertedLength); + + return buffer; +} + + +char* +fromUnsignedLongInteger(u64 value, + char* buffer, + usize length, + u8 base, + bool capitalized) +{ + // Do large ints in two passes. First do the high-order bits, then the lower order bits. + usize convertedLength; + convertedLength = _doConvertFromInteger(u32(value >> 32), buffer, length, base, capitalized); + convertedLength += _doConvertFromInteger(u32(value), &buffer[convertedLength], length - convertedLength, base, capitalized); + if (convertedLength < length) { + buffer[convertedLength] = '\0'; + } + reverse(buffer, convertedLength); + return buffer; } diff --git a/src/kstd/CString.hh b/src/kstd/CString.hh index faba4f2..d02d039 100644 --- a/src/kstd/CString.hh +++ b/src/kstd/CString.hh @@ -11,11 +11,20 @@ namespace kstd { namespace CString { -/** Find the length of a C string. */ -usize length(char *str); +/** + * Find the length of a C string. + * + * @param [in] str The string whose length we should find + * @param [in] max Maximum number of characters to search + * @return Length of the string + */ +usize length(const char *str, usize max = -1); /** Copy a string. */ -char* copy(char* dst, const char* src, usize length); +char* copy(char* dst, const char* src, usize max); + +/** Reverse a string. */ +char* reverse(char* str, usize max); /** Destructively convert an ASCII C String to uppercase. */ void uppercase(char *str); @@ -24,11 +33,24 @@ void uppercase(char *str); * @defgroup To-String Converters */ -/** Convert an integer to a string. */ -char* fromInteger(int value, char *str, usize length); +/** + * Convert a signed integer to a string. + * + * @param [in] value The value to convert + * @param [in,out] buffer Buffer to write to + * @param [in] length Length of the buffer + * @param [in] base Base to convert to. Default is base 10. + * @param [in] capitalized Should the alphabetic digits be capitalized? Default is false. + * @{ + */ +char* fromInteger(i32 value, char* buffer, usize length, u8 base = 10, bool capitalized = false); +char* fromUnsignedInteger(u32 value, char* buffer, usize length, u8 base = 10, bool capitalized = false); +char* fromLongInteger(i64 value, char* buffer, usize length, u8 base = 10, bool capitalized = false); +char* fromUnsignedLongInteger(u64 value, char* buffer, usize length, u8 base = 10, bool capitalized = false); +/** @} */ /** Convert a bool to a string. */ -char* fromBool(bool value, char *str, usize length); +char* fromBool(bool value, char* str, usize length); /** @} */