Lots of CString clean up; attempt #1 at implementing int to string conversion

Long (64-bit) ints are hard to do on 32-bit...
This commit is contained in:
Eryn Wells 2016-03-20 12:56:07 -04:00
parent d8b05620cc
commit d2d7fac4df
2 changed files with 169 additions and 16 deletions

View file

@ -13,10 +13,11 @@ namespace kstd {
namespace CString { namespace CString {
usize usize
length(char* str) length(const char* str,
usize max)
{ {
usize i; usize i;
for (i = 0; str[i] != '\0'; i++); for (i = 0; str[i] != '\0' && i < max; i++);
return i; return i;
} }
@ -24,9 +25,10 @@ length(char* str)
char* char*
copy(char* dst, copy(char* dst,
const char* src, 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]; dst[i] = src[i];
if (src[i] == '\0') { if (src[i] == '\0') {
break; 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 void
uppercase(char *str) uppercase(char* str)
{ {
for (char *p = str; *p != '\0'; p++) { for (char *p = str; *p != '\0'; p++) {
if (Char::isLower(*p)) { if (Char::isLower(*p)) {
@ -50,12 +69,124 @@ uppercase(char *str)
* Converters * Converters
*/ */
char* /**
fromInteger(int value, * Converts `value` to an un-reversed CString without a null terminator. It is
char* str, * expected that callers of this function will append a null terminator and
usize length) * 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;
} }

View file

@ -11,11 +11,20 @@
namespace kstd { namespace kstd {
namespace CString { 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. */ /** 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. */ /** Destructively convert an ASCII C String to uppercase. */
void uppercase(char *str); void uppercase(char *str);
@ -24,11 +33,24 @@ void uppercase(char *str);
* @defgroup To-String Converters * @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. */ /** Convert a bool to a string. */
char* fromBool(bool value, char *str, usize length); char* fromBool(bool value, char* str, usize length);
/** @} */ /** @} */