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++
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;
|
|
}
|