Patrick Kelley 8fd444092b initial
2025-05-07 15:35:15 -04:00

255 lines
5.6 KiB
C++

#include "pch.h"
#include <StrStream.h>
#include <Math/Int128.h>
using namespace std;
class Int128StrStream : public StrStream {
public:
Int128StrStream(ostream &out) : StrStream(out) {
}
Int128StrStream(wostream &out) : StrStream(out) {
}
Int128StrStream &operator<<(const _uint128 &n);
Int128StrStream &operator<<(const _int128 &n);
};
Int128StrStream &Int128StrStream::operator<<(const _uint128 &n) {
FormatFlags flg = flags() & ~ios::showpos; // never show +/- for unsigned
const UINT radix = this->radix();
TCHAR buf[200];
switch(radix) {
case 8 :
case 16:
if(n.isZero()) { // dont show base-prefix for 0
flg &= ~ios::showbase;
}
// NB..continue case
case 10:
_ui128tot(n, buf, radix);
if((radix == 16) && (flg & ios::uppercase)) {
_tcsupr(buf);
}
break;
}
formatFilledNumericField(buf, false, flg);
return *this;
}
Int128StrStream &Int128StrStream::operator<<(const _int128 &n) {
FormatFlags flg = flags();
const UINT radix = this->radix();
bool negative;
TCHAR buf[200];
switch(radix) {
case 8 :
case 16:
negative = false;
_ui128tot((_uint128&)n, buf, radix);
if((radix == 16) && (flg & ios::uppercase)) {
_tcsupr(buf);
}
if(n.isZero()) { // dont show base-prefix for 0
flg &= ~ios::showbase;
}
break;
case 10:
{ negative = (n < 0);
const _uint128 v = negative ? -n : n;
_ui128tot(v, buf, 10);
}
break;
}
formatFilledNumericField(buf, negative, flg);
return *this;
}
template <class IStreamType, class CharType> IStreamType &getInt128(IStreamType &in, _int128 &n) {
IStreamScanner<IStreamType, CharType> scanner(in);
CharType ch = scanner.peek();
bool gotDigits = false;
_int128 result;
switch(ch) {
case '-':
case '+':
ch = scanner.next();
}
switch(scanner.radix()) {
case 10:
while(iswdigit(ch)) {
ch = scanner.next();
gotDigits = true;
}
if(gotDigits) {
errno = 0;
result = _tcstoi128(scanner.getBuffer().cstr(), NULL, 10);
}
break;
case 16:
{ if(ch == '0') {
ch = scanner.next();
if((ch == 'x') || (ch == 'X')) {
ch = scanner.next();
} else {
gotDigits = true;
}
}
while(iswxdigit(ch)) {
ch = scanner.next();
gotDigits = true;
}
if(gotDigits) {
errno = 0;
String s = scanner.getBuffer();
intptr_t index;
if(((index = s.find(_T("0x"))) >= 0) || ((index = s.find(_T("0X"))) >= 0)) {
s.remove(index, 2);
}
result = _tcstoi128(s.cstr(), NULL, 16);
}
}
break;
case 8:
{ if(ch == '0') {
ch = scanner.next();
if(!iswodigit(ch)) {
gotDigits = true;
}
}
while(iswodigit(ch)) {
ch = scanner.next();
gotDigits = true;
}
if(gotDigits) {
errno = 0;
result = _tcstoi128(scanner.getBuffer().cstr(), NULL, 8);
}
}
break;
}
scanner.endScan(gotDigits && (errno == 0));
if(gotDigits) {
n = result;
}
return in;
}
template <class IStreamType, class CharType> IStreamType &getUint128(IStreamType &in, _uint128 &n) {
IStreamScanner<IStreamType, CharType> scanner(in);
CharType ch = scanner.peek();
bool gotDigits = false;
_uint128 result;
switch (ch) {
case '-':
case '+':
ch = scanner.next();
}
switch(scanner.radix()) {
case 10:
while(iswdigit(ch)) {
ch = scanner.next();
gotDigits = true;
}
if(gotDigits) {
errno = 0;
result = _tcstoui128(scanner.getBuffer().cstr(), NULL, 10);
}
break;
case 16:
{ if(ch == '0') {
ch = scanner.next();
if((ch == 'x') || (ch == 'X')) {
ch = scanner.next();
} else {
gotDigits = true;
}
}
while(iswxdigit(ch)) {
ch = scanner.next();
gotDigits = true;
}
if(gotDigits) {
errno = 0;
String s = scanner.getBuffer();
intptr_t index;
if(((index = s.find(_T("0x"))) >= 0) || ((index = s.find(_T("0X"))) >= 0)) {
s.remove(index, 2);
}
result = _tcstoui128(s.cstr(), NULL, 16);
}
}
break;
case 8:
{ if(ch == '0') {
ch = scanner.next();
if(!iswodigit(ch)) {
gotDigits = true;
}
}
while(iswodigit(ch)) {
ch = scanner.next();
gotDigits = true;
}
if(gotDigits) {
errno = 0;
result = _tcstoui128(scanner.getBuffer().cstr(), NULL, 8);
}
}
break;
}
scanner.endScan(gotDigits && (errno == 0));
if(gotDigits) {
n = result;
}
return in;
}
template <class OStreamType, class I128Type> OStreamType &putI128(OStreamType &out, const I128Type &n) {
Int128StrStream buf(out);
buf << n;
out << (String&)buf;
if(out.flags() & ios::unitbuf) {
out.flush();
}
return out;
}
istream &operator>>(istream &s, _int128 &n) {
return getInt128<istream, char>(s, n);
}
ostream &operator<<(ostream &s, const _int128 &n) {
return putI128(s, n);
}
wistream &operator>>(wistream &s, _int128 &n) {
return getInt128<wistream, wchar_t>(s, n);
}
wostream &operator<<(wostream &s, const _int128 &n) {
return putI128(s, n);
}
istream &operator>>(istream &s, _uint128 &n) {
return getUint128<istream, char>(s, n);
}
ostream &operator<<(ostream &s, const _uint128 &n) {
return putI128(s, n);
}
wistream &operator>>(wistream &s, _uint128 &n) {
return getUint128<wistream, wchar_t>(s, n);
}
wostream &operator<<(wostream &s, const _uint128 &n) {
return putI128(s, n);
}