Handout
This commit is contained in:
181
object/outputstream.cc
Normal file
181
object/outputstream.cc
Normal file
@@ -0,0 +1,181 @@
|
||||
#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;
|
||||
}
|
||||
Reference in New Issue
Block a user