mirror of
https://github.com/wichtounet/thor-os.git
synced 2025-09-19 09:35:15 -04:00
Add printf support to the user lib
This commit is contained in:
parent
b3039d01ca
commit
4ba26a4227
@ -49,22 +49,6 @@ void print_char(size_t line, size_t column, char c){
|
||||
size_t current_line = 0;
|
||||
size_t current_column = 0;
|
||||
|
||||
template<typename N>
|
||||
uint64_t digits(N number){
|
||||
if(number < 10){
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint64_t i = 0;
|
||||
|
||||
while(number != 0){
|
||||
number /= 10;
|
||||
++i;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
template<int B, typename D>
|
||||
void print_unsigned(D number){
|
||||
if(number == 0){
|
||||
@ -265,7 +249,7 @@ void k_printf(const char* fmt, ...){
|
||||
auto arg = va_arg(va, int64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = digits(arg);
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
|
||||
@ -290,7 +274,7 @@ void k_printf(const char* fmt, ...){
|
||||
auto arg = va_arg(va, uint64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = digits(arg);
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
while(min_digits > 0){
|
||||
|
@ -27,4 +27,7 @@ void clear();
|
||||
size_t get_columns();
|
||||
size_t get_rows();
|
||||
|
||||
std::string sprintf(const std::string& format, ...);
|
||||
void printf(const std::string& format, ...);
|
||||
|
||||
#endif
|
||||
|
@ -5,6 +5,8 @@
|
||||
// http://www.boost.org/LICENSE_1_0.txt)
|
||||
//=======================================================================
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include "print.hpp"
|
||||
|
||||
void print(char c){
|
||||
@ -79,3 +81,199 @@ size_t get_rows(){
|
||||
: "rax");
|
||||
return value;
|
||||
}
|
||||
|
||||
std::string vsprintf(const std::string& format, va_list va){
|
||||
std::string s(format.size());
|
||||
|
||||
char ch;
|
||||
int fi = 0;
|
||||
|
||||
while ((ch = format[fi++])) {
|
||||
if(ch != '%'){
|
||||
s += ch;
|
||||
} else {
|
||||
ch = format[fi++];
|
||||
|
||||
size_t min_width = 0;
|
||||
while(ch >= '0' && ch <= '9'){
|
||||
min_width = 10 * min_width + (ch - '0');
|
||||
ch = format[fi++];
|
||||
}
|
||||
|
||||
size_t min_digits = 0;
|
||||
if(ch == '.'){
|
||||
ch = format[fi++];
|
||||
|
||||
while(ch >= '0' && ch <= '9'){
|
||||
min_digits = 10 * min_digits + (ch - '0');
|
||||
ch = format[fi++];
|
||||
}
|
||||
}
|
||||
|
||||
auto prev = s.size();
|
||||
|
||||
//Signed decimal
|
||||
if(ch == 'd'){
|
||||
auto arg = va_arg(va, int64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
|
||||
if(arg < 0){
|
||||
arg *= -1;
|
||||
s += '-';
|
||||
}
|
||||
|
||||
while(min_digits > 0){
|
||||
while(min_digits > 0){
|
||||
arg += '0';
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += std::to_string(arg);
|
||||
}
|
||||
//Unsigned Decimal
|
||||
else if(ch == 'u'){
|
||||
auto arg = va_arg(va, uint64_t);
|
||||
|
||||
if(min_digits > 0){
|
||||
size_t d = std::digits(arg);
|
||||
if(min_digits > d){
|
||||
min_digits -= d;
|
||||
while(min_digits > 0){
|
||||
while(min_digits > 0){
|
||||
arg += '0';
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s += std::to_string(arg);
|
||||
}
|
||||
//Hexadecimal
|
||||
else if(ch == 'h'){
|
||||
s += "0x";
|
||||
|
||||
uint8_t buffer[20];
|
||||
|
||||
auto arg = va_arg(va, uint64_t);
|
||||
size_t i = 0;
|
||||
|
||||
while(arg / 16 != 0){
|
||||
buffer[i++] = arg % 16;
|
||||
arg /= 16;
|
||||
}
|
||||
|
||||
buffer[i] = arg;
|
||||
|
||||
if(min_digits > 0 && min_digits > i){
|
||||
min_digits -= i + 1;
|
||||
while(min_digits > 0){
|
||||
arg += '0';
|
||||
--min_digits;
|
||||
}
|
||||
}
|
||||
|
||||
while(true){
|
||||
uint8_t digit = buffer[i];
|
||||
|
||||
if(digit < 10){
|
||||
s += static_cast<char>('0' + digit);
|
||||
} else {
|
||||
switch(digit){
|
||||
case 10:
|
||||
s += 'A';
|
||||
break;
|
||||
case 11:
|
||||
s += 'B';
|
||||
break;
|
||||
case 12:
|
||||
s += 'C';
|
||||
break;
|
||||
case 13:
|
||||
s += 'D';
|
||||
break;
|
||||
case 14:
|
||||
s += 'E';
|
||||
break;
|
||||
case 15:
|
||||
s += 'F';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(i == 0){
|
||||
break;
|
||||
}
|
||||
|
||||
--i;
|
||||
}
|
||||
}
|
||||
//Memory
|
||||
else if(ch == 'm'){
|
||||
auto memory= va_arg(va, uint64_t);
|
||||
|
||||
if(memory >= 1024 * 1024 * 1024){
|
||||
s += std::to_string(memory / (1024 * 1024 * 1024));
|
||||
s += "GiB";
|
||||
} else if(memory >= 1024 * 1024){
|
||||
s += std::to_string(memory / (1024 * 1024));
|
||||
s += "MiB";
|
||||
} else if(memory >= 1024){
|
||||
s += std::to_string(memory / 1024);
|
||||
s += "KiB";
|
||||
} else {
|
||||
s += std::to_string(memory);
|
||||
s += "B";
|
||||
}
|
||||
}
|
||||
//String
|
||||
else if(ch == 's'){
|
||||
auto arg = va_arg(va, const char*);
|
||||
s += arg;
|
||||
}
|
||||
|
||||
if(min_width > 0){
|
||||
size_t width = s.size() - prev;
|
||||
|
||||
if(min_width > width){
|
||||
min_width -= width;
|
||||
|
||||
while(min_width > 0){
|
||||
s += ' ';
|
||||
--min_width;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return std::move(s);
|
||||
}
|
||||
|
||||
std::string sprintf(const std::string& format, ...){
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
|
||||
auto s = vsprintf(format, va);
|
||||
|
||||
va_end(va);
|
||||
|
||||
return std::move(s);
|
||||
}
|
||||
|
||||
void printf(const std::string& format, ...){
|
||||
va_list va;
|
||||
va_start(va, format);
|
||||
|
||||
auto s = vsprintf(format, va);
|
||||
print(s);
|
||||
|
||||
va_end(va);
|
||||
}
|
||||
|
@ -170,6 +170,33 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
basic_string& operator+=(const basic_string& rhs){
|
||||
if(!_data || _capacity <= _size + rhs.size()){
|
||||
_capacity = _capacity ? _capacity * 2 : 1;
|
||||
|
||||
if(_capacity < _size + rhs.size()){
|
||||
_capacity = _size + rhs.size() + 1;
|
||||
}
|
||||
|
||||
auto new_data = new CharT[_capacity];
|
||||
|
||||
if(_data){
|
||||
std::copy_n(new_data, _data, _size);
|
||||
delete[] _data;
|
||||
}
|
||||
|
||||
_data = new_data;
|
||||
}
|
||||
|
||||
std::copy_n(_data + _size, rhs.c_str(), rhs.size());
|
||||
|
||||
_size += rhs.size();
|
||||
|
||||
_data[_size] = '\0';
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
//Accessors
|
||||
|
||||
size_t size() const {
|
||||
@ -288,6 +315,22 @@ inline uint64_t parse(const string& str){
|
||||
return parse(str.begin(), str.end());
|
||||
}
|
||||
|
||||
template<typename N>
|
||||
size_t digits(N number){
|
||||
if(number < 10){
|
||||
return 1;
|
||||
}
|
||||
|
||||
size_t i = 0;
|
||||
|
||||
while(number != 0){
|
||||
number /= 10;
|
||||
++i;
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
template<typename Char>
|
||||
std::vector<std::basic_string<Char>> split(const std::basic_string<Char>& s){
|
||||
std::vector<std::basic_string<Char>> parts;
|
||||
@ -310,6 +353,45 @@ std::vector<std::basic_string<Char>> split(const std::basic_string<Char>& s){
|
||||
return std::move(parts);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string to_string(T value);
|
||||
|
||||
template<>
|
||||
inline std::string to_string<uint64_t>(uint64_t value){
|
||||
if(value == 0){
|
||||
return "0";
|
||||
}
|
||||
|
||||
std::string s;
|
||||
|
||||
char buffer[20];
|
||||
int i = 0;
|
||||
|
||||
while(value != 0){
|
||||
buffer[i++] = '0' + value % 10;
|
||||
value /= 10;
|
||||
}
|
||||
|
||||
--i;
|
||||
|
||||
for(; i >= 0; --i){
|
||||
s += buffer[i];
|
||||
}
|
||||
|
||||
return std::move(s);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline std::string to_string<int64_t>(int64_t value){
|
||||
if(value < 0){
|
||||
std::string s("-");
|
||||
s += to_string(static_cast<uint64_t>(value));
|
||||
return std::move(s);
|
||||
} else {
|
||||
return to_string(static_cast<uint64_t>(value));
|
||||
}
|
||||
}
|
||||
|
||||
} //end of namespace std
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user