ifndef __IOSTREAM
define __IOSTREAM

include conio.inc
include stdio.inc
include stdlib.inc

define endl <"\n">

.template ostream

    flags size_t ?

    .operator << :real8 {
       .new convbuf[64]:char_t
        sprintf( &convbuf, &@CStr("%f"), _1 )
        fputs(&convbuf, stdout)
        }
    .operator << :real4 {
        cvtss2sd _1,_1
        ostream_shl_real8(rcx, _1)
        }
    .operator << :dword {
       .new convbuf[64]:char_t
        mov ecx,_1
        _ultoa( ecx, &convbuf, 10 )
        fputs(&convbuf, stdout)
        }
    .operator << :qword {
       .new convbuf[64]:char_t
        mov rcx,_1
        _ui64toa( rcx, &convbuf, 10 )
        fputs(&convbuf, stdout)
        }
    .operator << :sdword {
       .new convbuf[64]:char_t
        mov ecx,_1
        _itoa( ecx, &convbuf, 10 )
        fputs(&convbuf, stdout)
        }
    .operator << :sqword {
       .new convbuf[64]:char_t
        mov this,_1
        _i64toa( this, &convbuf, 10 )
        fputs(&convbuf, stdout)
        }
    .operator << :sbyte {
        movsx   edx,_1
        ostream_shl_sdword(this, edx)
        }
    .operator << :sword {
        movsx   edx,_1
        ostream_shl_sdword(this, edx)
        }
    .operator << :byte {
        movzx   edx,_1
        ostream_shl_dword(this, edx)
        }
    .operator << :word {
        movzx   edx,_1
        ostream_shl_dword(this, edx)
        }
    .operator << :abs {
        ostream_shl_sdword(this, _1)
        }
    .operator << :ptr sbyte {
        mov this,_1
        fputs(this, stdout)
        }
    .operator << :ptr word {
        mov this,_1
        fputws(this, stdout)
        }
    .ends

.template wostream

    flags size_t ?

    .operator << :real8 {
       .new convbuf[64]:wchar_t
        swprintf( &convbuf, &@CStr("%f"), _1 )
        fputws(&convbuf, stdout)
        }
    .operator << :real4 {
        cvtss2sd _1,_1
        wostream_shl_real8(rcx, _1)
        }
    .operator << :dword {
       .new convbuf[64]:wchar_t
        mov ecx,_1
        _ultow( ecx, &convbuf, 10 )
        fputws(&convbuf, stdout)
        }
    .operator << :qword {
       .new convbuf[64]:wchar_t
        mov rcx,_1
        _ui64tow( rcx, &convbuf, 10 )
        fputws(&convbuf, stdout)
        }
    .operator << :sdword {
       .new convbuf[64]:wchar_t
        mov ecx,_1
        _itow( ecx, &convbuf, 10 )
        fputws(&convbuf, stdout)
        }
    .operator << :sqword {
       .new convbuf[64]:wchar_t
        mov rcx,_1
        _i64tow( rcx, &convbuf, 10 )
        fputws(&convbuf, stdout)
        }
    .operator << :sbyte {
        movsx   edx,_1
        wostream_shl_sdword(this, edx)
        }
    .operator << :sword {
        movsx   edx,_1
        wostream_shl_sdword(this, edx)
        }
    .operator << :byte {
        movzx   edx,_1
        wostream_shl_dword(this, edx)
        }
    .operator << :word {
        movzx   edx,_1
        wostream_shl_dword(this, edx)
        }
    .operator << :ptr sbyte {
        mov rcx,_1
        fputs(rcx, stdout)
        }
    .operator << :ptr word {
        mov rcx,_1
        fputws(rcx, stdout)
        }
    .ends

    .data
     align size_t
ifdef _UNICODE
     cstream wostream { 0 }
     wcout ptr wostream cstream
else
     cstream ostream { 0 }
     cout ptr ostream cstream
endif
endif
