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:
		
							parent
							
								
									d8b05620cc
								
							
						
					
					
						commit
						d2d7fac4df
					
				
					 2 changed files with 169 additions and 16 deletions
				
			
		| 
						 | 
				
			
			@ -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;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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);
 | 
			
		||||
 | 
			
		||||
/** @} */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue