#include #include static void BufferAdd(ASCII* buffer, Size bufferSize, Size* written, ASCII character) { if (*written + 1 < bufferSize) { buffer[*written] = character; } (*written)++; } void* StringSet(BytePointer destination, ASCII value, Size count) { BytePointer savedDestination = destination; while (count--) { *destination++ = (UInt8) value; } return savedDestination; } void* MemoryCopy(void* destination, const void* source, Size count) { BytePointer destinationBuffer = (BytePointer) destination; const UInt8* sourceBuffer = (const UInt8*) source; while (count >= 8) { *(UInt64*) destinationBuffer = *(const UInt64*) sourceBuffer; destinationBuffer += 8; sourceBuffer += 8; count -= 8; } while (count > 0) { *destinationBuffer++ = *sourceBuffer++; count--; } return destination; } Int32 StringCompare(const ASCII* firstString, const ASCII* secondString) { while (*firstString && (*firstString == *secondString)) { firstString++; secondString++; } return *(const UInt8*) firstString - *(const UInt8*) secondString; } Int32 StringCompareWithLimit(const ASCII* firstString, const ASCII* secondString, Size limit) { while (limit > 0) { if (*firstString != *secondString) return *(const UInt8*) firstString - *(const UInt8*) secondString; if (*firstString == '\0') return 0; firstString++; secondString++; limit--; } return 0; } ASCII* StringCopy(ASCII* destination, const ASCII* source) { ASCII* saved = destination; while (*source) *destination++ = *source++; *destination = 0; return saved; } ASCII* StringCopyWithLimit(ASCII* destination, const ASCII* source, Size limit) { ASCII* saved = destination; while (*source && limit > 0) { *destination++ = *source++; limit--; } while (limit > 0) { *destination++ = 0; limit--; } return saved; } Size StringGetLength(const ASCII* string) { Size result = 0; for (result = 0; string[result]; result++); return result; } const ASCII* StringFindLastOccurrenceOfCharacter(const ASCII* string, ASCII separator) { const ASCII* lastSeparator = 0; do { if (*string == separator) lastSeparator = string; } while (*string++); return lastSeparator; } Int32 StringFormatVariadic(ASCII* string, Size size, const ASCII* format, va_list args) { Size written = 0; for (Size i = 0; format[i] != '\0'; i++) { if (format[i] == '%') { i++; if (format[i] == '\0') break; switch (format[i]) { case 's': { const ASCII* vaArgString = va_arg(args, const ASCII*); if (!vaArgString) vaArgString = "(null)"; while (*vaArgString) BufferAdd(string, size, &written, *vaArgString++); break; } case 'c': { ASCII character = (ASCII)va_arg(args, Int); BufferAdd(string, size, &written, character); break; } case 'd': { Int64 number = va_arg(args, Int); if (number < 0) { BufferAdd(string, size, &written, '-'); number = -number; } UInt64 unsignedNumber = (UInt64)number; ASCII tempBuffer[32]; Size position = 0; if (unsignedNumber == 0) tempBuffer[position++] = '0'; while (unsignedNumber > 0) { tempBuffer[position++] = (ASCII)((unsignedNumber % 10) + '0'); unsignedNumber /= 10; } while (position > 0) BufferAdd(string, size, &written, tempBuffer[--position]); break; } case 'x': case 'X': { UInt64 unsignedNumber = va_arg(args, UInt64); UInt8 padding = (format[i] == 'X') ? 16 : 0; ASCII tempBuffer[32]; Size position = 0; static const ASCII kHexDigits[] = "0123456789ABCDEF"; if (unsignedNumber == 0 && padding == 0) tempBuffer[position++] = '0'; while (unsignedNumber > 0) { tempBuffer[position++] = kHexDigits[unsignedNumber % 16]; unsignedNumber /= 16; } while (position < (Size)padding) tempBuffer[position++] = '0'; while (position > 0) BufferAdd(string, size, &written, tempBuffer[--position]); break; } case '%': { BufferAdd(string, size, &written, '%'); break; } default: { BufferAdd(string, size, &written, '%'); BufferAdd(string, size, &written, format[i]); break; } } } else { BufferAdd(string, size, &written, format[i]); } } if (size > 0) { if (written < size) string[written] = '\0'; else string[size - 1] = '\0'; } return (Int32)written; } Int32 StringFormat(ASCII* destination, UInt64 size, const ASCII* format, ...) { va_list args; va_start(args, format); Int32 returnValue = StringFormatVariadic(destination, size, format, args); va_end(args); return returnValue; }