#ifdef NALL_STRING_CPP char* strlower(char *str) { if(!str) return 0; int i = 0; while(str[i]) { str[i] = chrlower(str[i]); i++; } return str; } char* strupper(char *str) { if(!str) return 0; int i = 0; while(str[i]) { str[i] = chrupper(str[i]); i++; } return str; } char* strtr(char *dest, const char *before, const char *after) { if(!dest || !before || !after) return dest; int sl = strlen(dest), bsl = strlen(before), asl = strlen(after); if(bsl != asl || bsl == 0) return dest; //patterns must be the same length for 1:1 replace for(unsigned i = 0; i < sl; i++) { for(unsigned l = 0; l < bsl; l++) { if(dest[i] == before[l]) { dest[i] = after[l]; break; } } } return dest; } uintmax_t strhex(const char *str) { if(!str) return 0; uintmax_t result = 0; //skip hex identifiers 0x and $, if present if(*str == '0' && (*(str + 1) == 'X' || *(str + 1) == 'x')) str += 2; else if(*str == '$') str++; while(*str) { uint8_t x = *str++; if(x >= '0' && x <= '9') x -= '0'; else if(x >= 'A' && x <= 'F') x -= 'A' - 10; else if(x >= 'a' && x <= 'f') x -= 'a' - 10; else break; //stop at first invalid character result = result * 16 + x; } return result; } intmax_t strsigned(const char *str) { if(!str) return 0; intmax_t result = 0; bool negate = false; //check for negation if(*str == '-') { negate = true; str++; } while(*str) { uint8_t x = *str++; if(x >= '0' && x <= '9') x -= '0'; else break; //stop at first invalid character result = result * 10 + x; } return !negate ? result : -result; } uintmax_t strunsigned(const char *str) { if(!str) return 0; uintmax_t result = 0; while(*str) { uint8_t x = *str++; if(x >= '0' && x <= '9') x -= '0'; else break; //stop at first invalid character result = result * 10 + x; } return result; } uintmax_t strbin(const char *str) { if(!str) return 0; uintmax_t result = 0; //skip bin identifiers 0b and %, if present if(*str == '0' && (*(str + 1) == 'B' || *(str + 1) == 'b')) str += 2; else if(*str == '%') str++; while(*str) { uint8_t x = *str++; if(x == '0' || x == '1') x -= '0'; else break; //stop at first invalid character result = result * 2 + x; } return result; } double strdouble(const char *str) { if(!str) return 0.0; bool negate = false; //check for negation if(*str == '-') { negate = true; str++; } intmax_t result_integral = 0; while(*str) { uint8_t x = *str++; if(x >= '0' && x <= '9') x -= '0'; else if(x == '.') break; //break loop and read fractional part else return (double)result_integral; //invalid value, assume no fractional part result_integral = result_integral * 10 + x; } intmax_t result_fractional = 0; while(*str) { uint8_t x = *str++; if(x >= '0' && x <= '9') x -= '0'; else break; //stop at first invalid character result_fractional = result_fractional * 10 + x; } //calculate fractional portion double result = (double)result_fractional; while((uintmax_t)result > 0) result /= 10.0; result += (double)result_integral; return !negate ? result : -result; } // size_t strhex(char *str, uintmax_t value, size_t length /* = 0 */) { if(length == 0) length -= 1U; //"infinite" length size_t initial_length = length; //count number of digits in value int digits_integral = 1; uintmax_t digits_integral_ = value; while(digits_integral_ /= 16) digits_integral++; int digits = digits_integral; if(!str) return digits + 1; //only computing required length? length = nall::min(digits, length - 1); str += length; //seek to end of target string *str = 0; //set null terminator while(length--) { uint8_t x = value % 16; value /= 16; *--str = x < 10 ? (x + '0') : (x + 'a' - 10); //iterate backwards to write string } return nall::min(initial_length, digits + 1); } size_t strsigned(char *str, intmax_t value_, size_t length /* = 0 */) { if(length == 0) length = -1U; //"infinite" length size_t initial_length = length; bool negate = value_ < 0; uintmax_t value = value_ >= 0 ? value_ : -value_; //count number of digits in value int digits_integral = 1; uintmax_t digits_integral_ = value; while(digits_integral_ /= 10) digits_integral++; int digits = (negate ? 1 : 0) + digits_integral; if(!str) return digits + 1; //only computing required length? length = nall::min(digits, length - 1); str += length; //seek to end of target string *str = 0; //set null terminator while(length && digits_integral--) { uint8_t x = '0' + (value % 10); value /= 10; *--str = x; //iterate backwards to write string length--; } if(length && negate) { *--str = '-'; } return nall::min(initial_length, digits + 1); } size_t strunsigned(char *str, uintmax_t value, size_t length /* = 0 */) { if(length == 0) length = -1U; //"infinite" length size_t initial_length = length; //count number of digits in value int digits_integral = 1; uintmax_t digits_integral_ = value; while(digits_integral_ /= 10) digits_integral++; int digits = digits_integral; if(!str) return digits_integral + 1; //only computing required length? length = nall::min(digits, length - 1); str += length; //seek to end of target string *str = 0; //set null terminator while(length--) { uint8_t x = '0' + (value % 10); value /= 10; *--str = x; //iterate backwards to write string } return nall::min(initial_length, digits + 1); } size_t strbin(char *str, uintmax_t value, size_t length /* = 0 */) { if(length == 0) length = -1U; //"infinite" length size_t initial_length = length; //count number of digits in value int digits_integral = 1; uintmax_t digits_integral_ = value; while(digits_integral_ /= 2) digits_integral++; int digits = digits_integral; if(!str) return digits + 1; //only computing required length? length = nall::min(digits, length - 1); str += length; //seek to end of target string *str = 0; //set null terminator while(length--) { uint8_t x = '0' + (value % 2); value /= 2; *--str = x; //iterate backwards to write string } return nall::min(initial_length, digits + 1); } //using sprintf is certainly not the most ideal method to convert //a double to a string ... but attempting to parse a double by //hand, digit-by-digit, results in subtle rounding errors. // //note: length parameter is currently ignored. //it remains for consistency and possible future support. size_t strdouble(char *str, double value, size_t length /* = 0 */) { char buffer[256]; sprintf(buffer, "%f", value); //remove excess 0's in fraction (2.500000 -> 2.5) for(char *p = buffer; *p; p++) { if(*p == '.') { char *p = buffer + strlen(buffer) - 1; while(*p == '0') { if(*(p - 1) != '.') *p = 0; //... but not for eg 1.0 -> 1. p--; } break; } } length = strlen(buffer); if(str) strcpy(str, buffer); return length + 1; } #endif