You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

182 lines
4.8 KiB
C++

#include "outputstream.h"
// operator <<: Converts the value in given data type to a string
// Print a single character (trivial)
OutputStream& OutputStream::operator<<(char c) {
put(c);
return *this;
}
OutputStream& OutputStream::operator<<(unsigned char c) {
return *this << static_cast<char>(c);
}
// Printing a null-terminated string
OutputStream& OutputStream::operator<<(const char* string) {
while ((*string) != '\0') {
put(*string);
string++;
}
return *this;
}
OutputStream& OutputStream::operator<<(bool b) {
return *this << (b ? "true" : "false");
}
// Print integral numbers in number system base.
// All signed types are promoted to long long,
// all unsigned types to unsigned long long.
OutputStream& OutputStream::operator<<(short ival) {
return *this << static_cast<long long>(ival);
}
OutputStream& OutputStream::operator<<(unsigned short ival) {
return *this << static_cast<unsigned long long>(ival);
}
OutputStream& OutputStream::operator<<(int ival) {
return *this << static_cast<long long>(ival);
}
OutputStream& OutputStream::operator<<(unsigned int ival) {
return *this << static_cast<unsigned long long>(ival);
}
OutputStream& OutputStream::operator<<(long ival) {
return *this << static_cast<long long>(ival);
}
OutputStream& OutputStream::operator<<(unsigned long ival) {
return *this << static_cast<unsigned long long>(ival);
}
// Print a signed , integral number.
OutputStream& OutputStream::operator<<(long long ival) {
/* Print '-' if number is negative
*
* In case ival is equal to LONG_LONG_MIN (0x8000000000000000), this
* multiplication with -1 will overflow and, as for all signed overflows,
* is not specified in C/C++. Thus, this operation will only work when
* the system uses two's complement:
* ~(0x8000000000000000) + 1 = 0x7fffffffffffffff + 1 = 0x8000000000000000
*
* When casting 0x8000000000000000 to unsigned long long, the value will
* be (correctly) interpreted as -(LONG_LONG_MIN).
*
* A solution conforming (more) to the standard could be:
* if ((ival < 0) && (base == 10)) {
* put('-');
* if (ival == LONG_LONG_MIN) {
* return *this << static_cast<unsigned long long>(LONG_LONG_MAX -
* (LONG_LONG_MAX + LONG_LONG_MIN)); } else { return *this <<
* static_cast<unsigned long long>(-ival);
* }
* (However it introduces additional overhead)
*/
if ((ival < 0) && (base == 10)) {
put('-');
ival = -ival;
}
// Print the remaining positive number using the unsigned output
return *this << static_cast<unsigned long long>(ival);
}
// Print a unsigned, integral number.
OutputStream& OutputStream::operator<<(unsigned long long ival) {
if (base == 0) {
base = 16;
}
if (base == 2) {
put('0');
put('b');
} else if (base == 8) {
put('0'); // octal numbers are prefixed with 0
} else if (base == 16) {
put('0'); // hexadecimal numbers are prefixed with 0x
put('x');
}
// Determine the largest potency in the number system used, which is
// still smaller than the number to be printed
unsigned long long div;
for (div = 1; ival / div >= static_cast<unsigned long long>(base);
div *= base) {
}
// print number char by char
for (; div > 0; div /= static_cast<unsigned long long>(base)) {
auto digit = ival / div;
if (digit < 10) {
put(static_cast<char>('0' + digit));
} else {
put(static_cast<char>('a' + digit - 10));
}
ival %= div;
}
return *this;
}
// Print a pointer as hexadecimal number
OutputStream& OutputStream::operator<<(const void* ptr) {
int oldbase = base;
base = 16;
*this << reinterpret_cast<uintptr_t>(ptr);
base = oldbase;
return *this;
}
// Calls one of the manipulator functions
OutputStream& OutputStream::operator<<(OutputStream& (*f)(OutputStream&)) {
return f(*this);
}
/* STREAM MANIPULATORS
*
* The functions below take and return a reference to an OutputStream object
* and are called by OutputStream& operator << (OutputStream& (*f)
* (OutputStream&)); The purpose of theses manipulator functions is modifying
* the behavior of the stream the are executed on, such as changing the number
* system.
*/
// flush: Explicit buffer flush
OutputStream& flush(OutputStream& os) {
os.flush();
return os;
}
// endl: Inserts a newline to the output
OutputStream& endl(OutputStream& os) {
os << '\n' << flush;
return os;
}
// bin: Selects the binary number system
OutputStream& bin(OutputStream& os) {
os.base = 2;
return os;
}
// oct: Selects the octal number system
OutputStream& oct(OutputStream& os) {
os.base = 8;
return os;
}
// dec: Selects the decimal number system
OutputStream& dec(OutputStream& os) {
os.base = 10;
return os;
}
// hex: Selects the hexadecimal number system
OutputStream& hex(OutputStream& os) {
os.base = 16;
return os;
}