diff --git a/changelog.txt b/changelog.txt index 1dd51c7fc6..62da10c6fd 100644 --- a/changelog.txt +++ b/changelog.txt @@ -23,6 +23,7 @@ Version 1.07.0 - SELECT statement will accept UDT as Z|WSTRING to return a Z|WSTRING - SWAP statement will accept UDT as Z|WSTRING - IIF function will accept UDT as Z|WSTRING +- PRINT/LPRINT/WRITE will accept UDT as Z|WSTRING [fixed] - sf.net #881: C backend: support for varadic function parameters in gcc using __builtin_va_list type and related macros diff --git a/src/compiler/rtl-print.bas b/src/compiler/rtl-print.bas index 3eeb9f9ca9..254756d63b 100644 --- a/src/compiler/rtl-print.bas +++ b/src/compiler/rtl-print.bas @@ -690,6 +690,8 @@ function rtlPrint _ f = PROCLOOKUP( PRINTVOID ) end if else + astTryOvlStringCONV( expr ) + '' UDT? try to convert to string with type casting op overloading select case typeGet( astGetDataType( expr ) ) case FB_DATATYPE_STRUCT, FB_DATATYPE_ENUM @@ -901,6 +903,8 @@ function rtlWrite _ if( expr = NULL ) then f = PROCLOOKUP( WRITEVOID ) else + astTryOvlStringCONV( expr ) + '' UDT? try to convert to string with type casting op overloading select case astGetDataType( expr ) case FB_DATATYPE_STRUCT, FB_DATATYPE_ENUM @@ -1071,6 +1075,8 @@ function rtlPrintUsing _ exit function end if + astTryOvlStringCONV( expr ) + '' UDT? try to convert to double with type casting op overloading select case astGetDataType( expr ) case FB_DATATYPE_STRUCT, FB_DATATYPE_ENUM diff --git a/tests/udt-wstring/print.bas b/tests/udt-wstring/print.bas new file mode 100644 index 0000000000..3a37e539c8 --- /dev/null +++ b/tests/udt-wstring/print.bas @@ -0,0 +1,145 @@ +#include "fbcunit.bi" +#include once "uwstring-fixed.bi" +#include once "chk-wstring.bi" + +#define ustring UWSTRING_FIXED + +#define PRINT_IF_UNEQUAL + +#define BUFFER_SIZE 50 + +#define QT(s) wstr("""" & wstr(s) & """") + +#define WPRINT( value, cmp ) _ + print #(1), value & ", " & QT(cmp) + +#define WPRINT_STR( value, cmp ) _ + print #(1), QT(value) & ", " & QT(cmp) + +#macro OPEN_FILE( fn ) + const TESTFILE = ("./udt-wstring/" & fn) + + open TESTFILE for output encoding "utf-16" as #1 +#endmacro + +#macro CLOSE_AND_TEST_FILE() + close #1 + + dim as wstring * BUFFER_SIZE sResult, sExpected + dim as integer errcount = 0 + open TESTFILE for input encoding "utf-16" as #1 + do until eof(1) + input #1, sResult, sExpected + if( sResult <> sExpected ) then +#ifdef PRINT_IF_UNEQUAL + print QT(sResult) & " <> " & QT(sExpected) + errcount += 1 +#endif + end if + CU_ASSERT_EQUAL( sResult, sExpected ) + loop + close #1 + + if errcount = 0 then + kill TESTFILE + end if +#endmacro + + +SUITE( fbc_tests.udt_wstring_.print_ ) + + TEST( numbers ) + + #macro check( dtype, value ) + scope + dim x as ustring = wstr(value) + dim cmp as wstring * BUFFER_SIZE = wstr( value ) + WPRINT( x, cmp ) + end scope + #endmacro + + OPEN_FILE( "print_numbers.txt" ) + + check( boolean, false ) + check( boolean, true ) + + check( byte, -128 ) + check( byte, -0 ) + check( byte, 127 ) + + check( ubyte, 0 ) + check( ubyte, 128 ) + check( ubyte, 255 ) + + check( short, -32768 ) + check( short, 0 ) + check( short, 32767 ) + + check( ushort, 0 ) + check( ushort, 32768 ) + check( ushort, 65535 ) + + check( long, -2147483648ll ) + check( long, 0 ) + check( long, 2147483647ull ) + + check( ulong, 0 ) + check( ulong, 2147483648ull ) + check( ulong, 4294967295ull ) + + check( longint, (-9223372036854775807ll-1ll) ) + check( longint, 0 ) + check( longint, 9223372036854775807ull ) + + check( ulongint, 0 ) + check( ulongint, 9223372036854775808ull ) + check( ulongint, 18446744073709551615ull ) + + check( single, -1.5 ) + check( single, -1.0 ) + check( single, -1.0 ) + check( single, -0.5 ) + check( single, 0.0 ) + check( single, 0.5 ) + check( single, 1.0) + check( single, 1.5 ) + check( single, 2.0 ) + check( single, 2.5 ) + + check( double, -1.5 ) + check( double, -1.0 ) + check( double, -1.0 ) + check( double, -0.5 ) + check( double, 0.0 ) + check( double, 0.5 ) + check( double, 1.0) + check( double, 1.5 ) + check( double, 2.0 ) + check( double, 2.5 ) + + CLOSE_AND_TEST_FILE() + + END_TEST + + TEST( strings ) + + #macro check( literal ) + scope + dim x as ustring = literal + WPRINT_STR( x, literal ) + end scope + #endmacro + + OPEN_FILE( "print_strings.txt" ) + + check( "" ) + check( " " ) + check( "0123456789" ) + check( "ABCDEFGHIJKLMNOP" ) + check( !"\u3041\u3043\u3045\u3047\u3049" ) + + CLOSE_AND_TEST_FILE() + + END_TEST + +END_SUITE diff --git a/tests/udt-zstring/print.bas b/tests/udt-zstring/print.bas new file mode 100644 index 0000000000..bca4b04707 --- /dev/null +++ b/tests/udt-zstring/print.bas @@ -0,0 +1,144 @@ +#include "fbcunit.bi" +#include once "uzstring-fixed.bi" +#include once "chk-zstring.bi" + +#define ustring UZSTRING_FIXED + +#define PRINT_IF_UNEQUAL + +#define BUFFER_SIZE 50 + +#define QT(s) str("""" & str(s) & """") + +#define ZPRINT( value, cmp ) _ + print #(1), value & ", " & QT(cmp) + +#define ZPRINT_STR( value, cmp ) _ + print #(1), QT(value) & ", " & QT(cmp) + +#macro OPEN_FILE( fn ) + const TESTFILE = ("./udt-zstring/" & fn) + + open TESTFILE for output encoding "utf-16" as #1 +#endmacro + +#macro CLOSE_AND_TEST_FILE() + close #1 + + dim as zstring * BUFFER_SIZE sResult, sExpected + dim as integer errcount = 0 + open TESTFILE for input encoding "utf-16" as #1 + do until eof(1) + input #1, sResult, sExpected + if( sResult <> sExpected ) then +#ifdef PRINT_IF_UNEQUAL + print QT(sResult) & " <> " & QT(sExpected) + errcount += 1 +#endif + end if + CU_ASSERT_EQUAL( sResult, sExpected ) + loop + close #1 + + if errcount = 0 then + kill TESTFILE + end if +#endmacro + + +SUITE( fbc_tests.udt_zstring_.print_ ) + + TEST( numbers ) + + #macro check( dtype, value ) + scope + dim x as ustring = str(value) + dim cmp as zstring * BUFFER_SIZE = str( value ) + ZPRINT( x, cmp ) + end scope + #endmacro + + OPEN_FILE( "print_numbers.txt" ) + + check( boolean, false ) + check( boolean, true ) + + check( byte, -128 ) + check( byte, -0 ) + check( byte, 127 ) + + check( ubyte, 0 ) + check( ubyte, 128 ) + check( ubyte, 255 ) + + check( short, -32768 ) + check( short, 0 ) + check( short, 32767 ) + + check( ushort, 0 ) + check( ushort, 32768 ) + check( ushort, 65535 ) + + check( long, -2147483648ll ) + check( long, 0 ) + check( long, 2147483647ull ) + + check( ulong, 0 ) + check( ulong, 2147483648ull ) + check( ulong, 4294967295ull ) + + check( longint, (-9223372036854775807ll-1ll) ) + check( longint, 0 ) + check( longint, 9223372036854775807ull ) + + check( ulongint, 0 ) + check( ulongint, 9223372036854775808ull ) + check( ulongint, 18446744073709551615ull ) + + check( single, -1.5 ) + check( single, -1.0 ) + check( single, -1.0 ) + check( single, -0.5 ) + check( single, 0.0 ) + check( single, 0.5 ) + check( single, 1.0) + check( single, 1.5 ) + check( single, 2.0 ) + check( single, 2.5 ) + + check( double, -1.5 ) + check( double, -1.0 ) + check( double, -1.0 ) + check( double, -0.5 ) + check( double, 0.0 ) + check( double, 0.5 ) + check( double, 1.0) + check( double, 1.5 ) + check( double, 2.0 ) + check( double, 2.5 ) + + CLOSE_AND_TEST_FILE() + + END_TEST + + TEST( strings ) + + #macro check( literal ) + scope + dim x as ustring = literal + ZPRINT_STR( x, literal ) + end scope + #endmacro + + OPEN_FILE( "print_strings.txt" ) + + check( "" ) + check( " " ) + check( "0123456789" ) + check( "ABCDEFGHIJKLMNOP" ) + + CLOSE_AND_TEST_FILE() + + END_TEST + +END_SUITE diff --git a/tests/wstring/print.bas b/tests/wstring/print.bas new file mode 100644 index 0000000000..4baf36a3e4 --- /dev/null +++ b/tests/wstring/print.bas @@ -0,0 +1,138 @@ +#include "fbcunit.bi" + +#define PRINT_IF_UNEQUAL + +#define BUFFER_SIZE 50 + +#define QT(s) wstr("""" & wstr(s) & """") + +#define WPRINT( value, cmp ) _ + print #(1), value & ", " & QT(cmp) + +#macro OPEN_FILE( fn ) + const TESTFILE = ("./wstring/" & fn) + + open TESTFILE for output encoding "utf-16" as #1 +#endmacro + +#macro CLOSE_AND_TEST_FILE() + close #1 + + dim as wstring * BUFFER_SIZE sResult, sExpected + dim as integer errcount = 0 + open TESTFILE for input encoding "utf-16" as #1 + do until eof(1) + input #1, sResult, sExpected + if( sResult <> sExpected ) then +#ifdef PRINT_IF_UNEQUAL + print QT(sResult) & " <> " & QT(sExpected) + errcount += 1 +#endif + end if + CU_ASSERT_EQUAL( sResult, sExpected ) + loop + close #1 + + if errcount = 0 then + kill TESTFILE + end if +#endmacro + + +SUITE( fbc_tests.wstring_.print_ ) + + TEST( numbers ) + + #macro check( dtype, value ) + scope + dim x as dtype = value + dim cmp as wstring * BUFFER_SIZE = wstr( value ) + WPRINT( x, cmp ) + end scope + #endmacro + + OPEN_FILE( "print_numbers.txt" ) + + check( boolean, false ) + check( boolean, true ) + + check( byte, -128 ) + check( byte, -0 ) + check( byte, 127 ) + + check( ubyte, 0 ) + check( ubyte, 128 ) + check( ubyte, 255 ) + + check( short, -32768 ) + check( short, 0 ) + check( short, 32767 ) + + check( ushort, 0 ) + check( ushort, 32768 ) + check( ushort, 65535 ) + + check( long, -2147483648ll ) + check( long, 0 ) + check( long, 2147483647ull ) + + check( ulong, 0 ) + check( ulong, 2147483648ull ) + check( ulong, 4294967295ull ) + + check( longint, (-9223372036854775807ll-1ll) ) + check( longint, 0 ) + check( longint, 9223372036854775807ull ) + + check( ulongint, 0 ) + check( ulongint, 9223372036854775808ull ) + check( ulongint, 18446744073709551615ull ) + + check( single, -1.5 ) + check( single, -1.0 ) + check( single, -1.0 ) + check( single, -0.5 ) + check( single, 0.0 ) + check( single, 0.5 ) + check( single, 1.0) + check( single, 1.5 ) + check( single, 2.0 ) + check( single, 2.5 ) + + check( double, -1.5 ) + check( double, -1.0 ) + check( double, -1.0 ) + check( double, -0.5 ) + check( double, 0.0 ) + check( double, 0.5 ) + check( double, 1.0) + check( double, 1.5 ) + check( double, 2.0 ) + check( double, 2.5 ) + + CLOSE_AND_TEST_FILE() + + END_TEST + + TEST( strings ) + + #macro check( literal ) + scope + dim x as wstring * BUFFER_SIZE = literal + WPRINT( x, literal ) + end scope + #endmacro + + OPEN_FILE( "print_strings.txt" ) + + check( "" ) + check( " " ) + check( "0123456789" ) + check( "ABCDEFGHIJKLMNOP" ) + check( !"\u3041\u3043\u3045\u3047\u3049" ) + + CLOSE_AND_TEST_FILE() + + END_TEST + +END_SUITE diff --git a/tests/wstring/print_using.bas b/tests/wstring/print_using.bas new file mode 100644 index 0000000000..107f1e70ed --- /dev/null +++ b/tests/wstring/print_using.bas @@ -0,0 +1,524 @@ +#include "fbcunit.bi" + +#define PRINT_IF_UNEQUAL + +#define BUFFER_SIZE 50 + +#define QT(s) wstr("""" & wstr(s) & """") + +'' last output on a line wrapper +#define PRINT_USING_N( fmt, num, cmp ) _ + print #(1), using ( QT(fmt) & ", " & QT("&") ); num; wstr(cmp) + +'' continuing output on a line wrapper +#define PRINT_USING_1( fmt, num, cmp ) _ + print #(1), using ( QT(fmt) & ", " & QT("&") & ", "); num; wstr(cmp); : _ + print #(1), , + +#define HASHES(n) wstring(n, asc("#")) +#define CARETS(n) wstring(n, asc("^")) +#define DOT "." + + +#macro OPEN_FILE( fn ) + const TESTFILE = ("./wstring/" & fn) + + open TESTFILE for output encoding "utf-16" as #1 +#endmacro + +#macro CLOSE_AND_TEST_FILE() + close #1 + + dim as wstring * BUFFER_SIZE sResult, sExpected + dim as integer errcount = 0 + open TESTFILE for input encoding "utf-16" as #1 + do until eof(1) + input #1, sResult, sExpected + if( sResult <> sExpected ) then +#ifdef PRINT_IF_UNEQUAL + print QT(sResult) & " <> " & QT(sExpected) + errcount += 1 +#endif + end if + CU_ASSERT_EQUAL( sResult, sExpected ) + loop + close #1 + + if errcount = 0 then + kill TESTFILE + end if +#endmacro + + +SUITE( fbc_tests.wstring_.print_using ) + + private sub test_ll( _ + byref fmt as wstring, _ + byval num as longint, _ + byref cmp as wstring, _ + byval do_fp as integer = 1) + + if num = clng(num) then + PRINT_USING_1( fmt & "%", clng(num), cmp & "%" ) + end if + if num = culng(num) then + PRINT_USING_1( fmt & "u", culng(num), cmp & "u" ) + end if + if cunsg(abs(num)) <= 1 shl 23 then + PRINT_USING_1( fmt & "_!", csng(num), cmp & "!" ) + end if + if do_fp andalso cunsg(abs(num)) <= 1ull shl 52 then + PRINT_USING_1( fmt & "_#", cdbl(num), cmp & "#" ) + end if + if num >= 0 then + PRINT_USING_1( fmt & "ull", culngint(num), cmp & "ull" ) + end if + + if num = cint(cbool(num)) and (instr(fmt, "&") = 0) then + PRINT_USING_1( fmt & "b", num, cmp & "b" ) + end if + + PRINT_USING_N( fmt & "ll", num, cmp & "ll" ) + + end sub + + private sub test_ull( _ + byref fmt as wstring, _ + byval num as ulongint, _ + byref cmp as wstring, _ + byval do_fp as integer = 1) + + if num < 1ull shl 31 then + PRINT_USING_1( fmt & "%", clng(num), cmp & "%" ) + end if + if num < 1ull shl 32 then + PRINT_USING_1( fmt & "u", culng(num), cmp & "u" ) + end if + if num <= 1ull shl 23 then + PRINT_USING_1( fmt & "_!", cdbl(num), cmp & "!" ) + end if + if do_fp andalso num <= 1ull shl 52 then + PRINT_USING_1( fmt & "_#", cdbl(num), cmp & "#" ) + end if + if num < 1ull shl 63 then + PRINT_USING_1( fmt & "ll", clngint(num), cmp & "ll" ) + end if + + PRINT_USING_N( fmt & "ull", num, cmp & "ull" ) + + end sub + + private sub test_dbl( _ + byref fmt as wstring, _ + byval num as double, _ + byref cmp as wstring) + + PRINT_USING_N( fmt & "_#", num, cmp & "#" ) + + end sub + + private sub test_sng2( _ + byref fmt as wstring, _ + byval num as single, byval num2 as single, _ + byref cmp as wstring) + + PRINT_USING_N( fmt & "_!", csng(num);csng(num2), cmp & "!" ) + + end sub + + private sub test_sng( _ + byref fmt as wstring, _ + byval num as double, _ + byref cmp as wstring, _ + byval do_dbl as integer = 1) + + '' note: num is a Double to prevent + '' decimal vals getting corrupted in Double test + + PRINT_USING_N( fmt & "_!", csng(num), cmp & "!" ) + if( do_dbl ) then + PRINT_USING_N( fmt & "_#", cdbl(num), cmp & "#" ) + end if + + end sub + + private sub test_str( _ + byref fmt as wstring, _ + byref s as wstring, _ + byref cmp as wstring) + + PRINT_USING_N( fmt & "_$", s, cmp & "$" ) + + end sub + + private sub test_bool( _ + byref fmt as wstring, _ + byref num as boolean, _ + byref cmp as wstring) + + if instr(fmt, "&") then + '' test true/false + PRINT_USING_N( fmt & "b", iif(num, "true", "false"), cmp & "b" ) + else + test_ll( fmt, clngint(num), cmp ) + end if + + end sub + + private function pow_ull( byval m as ulongint, byval n as integer ) as ulongint + + dim as ulongint ret = 1ull + + for i as integer = 1 to n + ret *= m + next i + + return ret + + end function + + '' statement parsing test + TEST( stmttest ) + OPEN_FILE( "print_using_stmttest.txt" ) + + print #1, "abc, abc" + print #1, using "&"; "def, def" + + print #1, "ghi"; ", "; using "&"; "ghi" + + print #1, """a"; spc(5); "b"", "; using """&&"""; "a"; spc(5); "b" + + print #1, """a"; tab(10); "b""" + print #1, using """&&"""; "a"; tab(10); "b" + + #if 0 + print #1, """"; "a", "b"; """" + print #1, using """&&"""; "a", "b" + + print #1, """a", , "b""" + print #1, using """&&"""; "a", , "b" + #endif + + CLOSE_AND_TEST_FILE() + END_TEST + + '' number test + TEST( numtest ) + + dim num as double, num_ll as longint, num_ull as ulongint + dim as wstring * BUFFER_SIZE fmt, cmp + dim as integer i, e + dim as single s + + OPEN_FILE( "print_using_numtest.txt" ) + + '' test 1, 12, 123, ... 1234567890124567890 (20 digs) + + test_ull( "#", 0, "0" ) + + fmt = "": cmp = "": num_ull = 0 + for i = 1 to 20 + num_ull = num_ull * 10 + i mod 10 + + fmt &= "#" + cmp &= i mod 10 + + test_ull( fmt, num_ull, cmp ) + next i + + '' Test that Singles can get double precision (except with "&") + '' (Note that a Single can easily store 2^-10 without loss of precision) + test_sng2( "#.##########, &", 2^-10, 2^-10, "0.0009765625, 9.765625E-4" ) + + '' test 2^-19 .. 2^63 (all fit within 20.20 digits without scaling) + + fmt = HASHES(20) & "." & HASHES(20) + for i = -19 to 63 + + if i >= 0 then + cmp = (1ull shl i) & "." + else + cmp = "0." & right( wstring(30, asc("0")) & pow_ull(5, -i), -i) + end if + while instr(cmp, ".") < instr(fmt, "."): cmp = " " & cmp: wend + while len(cmp) < len(fmt): cmp = cmp & "0": wend + + if i >= 0 then + num_ull = 1ull shl i + test_ull( fmt, num_ull, cmp ) + if num_ull <= 1ull shl 63 then + test_ll( fmt & "-", -csign(num_ull), cmp & "-" ) + end if + else + num = 2 ^ i + test_dbl( fmt, num, cmp ) + end if + next i + + '' test 1ull shl 54, 2^54 (double precision should cut off last digit on 2^54) + test_ull( fmt, 1ull shl 54, " 18014398509481984.00000000000000000000" ) + test_sng( fmt, 2 ^ 54, " 18014398509481980.00000000000000000000" ) + + + fmt = HASHES(2) & "." & HASHES(18) & CARETS(4) + + '' test 2^-23 (double precision should cut off last '5' digit and round up from ...25 to ...30) + '' (Use a Single value here because Linux + '' doesn't seem to emit decimal 2^-23 accurately for Doubles) + s = 2^-23 + test_sng( fmt, s, " 1.192092895507813000E-07" ) + + '' test 2^-22 .. 2^0 in floating-point (should all fit within double precision digits) + for i = -22 to 0 + num = 2 ^ i + + ' construct negative power of 2 for cmp + cmp = " " & pow_ull(5, -i) + cmp = left(cmp, 2) & "." & mid(cmp, 3) + e = len(fmt) - len(cmp) - 4 + cmp &= wstring(e, asc("0")) + cmp &= "E" & *iif(i - e + 18 < 0, @"-", @"+") & right("0" & abs(i-e+18), 2) + + test_sng( fmt, num, cmp ) + next i + + '' check that values are scaled/stored without loss of precision + '' (Doubles can't store odd numbers above 2^53=~.9e16) + fmt = HASHES(17) & DOT & CARETS(3) + test_dbl( fmt, 1e16 - 6, " 9999999999999994.E+0" ) + test_dbl( fmt, 1e15 -.5, " 9999999999999995.E-1" ) + test_dbl( fmt, 1e16 - 4, " 9999999999999996.E+0" ) + + CLOSE_AND_TEST_FILE() + + END_TEST + + '' format parsing test + TEST( fmttest ) + + OPEN_FILE( "print_using_fmttest.txt" ) + + print #1, using "_##_"; 9; + print #1, ",", "#9_" + + print #1, using "#_"; 3; 1; 4; + print #1, ",", "3_1_4_" + + + PRINT_USING_N( "&#&#.#&#^^^&&", _ + 1; 2; 3; 4.0; 5; 6E+0; 7; 8, _ + "1234.056E+078" ) + + test_ll( "$ #" , 1, "$ 1" ) + test_ll( "* #" , 1, "* 1" ) + test_ll( "*##" , 1, "* 1" ) + test_ll( "*$ #", 1, "*$ 1" ) + + test_ll( "$$" , 1, "$1" ) + test_ll( "**" , 1, "*1" ) + test_ll( "**####" , 123, "***123" ) + test_ll( "**$", 1, "*$1" ) + + test_ll( "**$####" , 456, "***$456" ) + test_ll( "+**$####" , 456, "***+$456" ) + + test_ll( "$$$" , 1, "$1$" ) + test_ll( "***" , 1, "*1*" ) + test_ll( "***$", 1, "*1*$" ) + test_ll( "**$$", 1, "*$1$" ) + + test_ll( ",#####" , 1234, ", 1234" ) + test_ll( "#,####" , 1234, " 1,234" ) + test_ll( "#####," , 1234, " 1,234" ) + test_ll( "#####.,", 1234, " 1234.," ) + test_ll( "#,###.^^^^", 1234, " 1234.E+00" ) + test_sng2( "#.#,##", 1.2, 34, "1.2,34" ) + + test_sng( ".##$", 0.01, ".01$" ) + test_sng( ".$$", 1, ".$1" ) + test_sng( ".#$", 0.1, ".1$" ) + test_sng( ".##", 0.01, ".01" ) + test_sng( ".##.", 0.01, ".01." ) + test_sng2( ".##.#", 0.01, 0.2, ".01.2" ) + + test_sng2( "##$$", 1, 2, " 1$2" ) + test_sng2( ".##$$", 0.01, 2, ".01$2" ) + + test_sng2( ".##$$", 0.01, 2, ".01$2" ) + + + test_sng( "#", -.4, "-" ) + test_sng( "##", -.4, "-0" ) + test_sng( "+#", -.4, "-0" ) + test_sng( "+#+", -.4, "-0+" ) + test_sng( "+#-", -.4, "-0-" ) + test_sng( "+#-", 0.4, "+0-" ) + + test_sng( "-###", 42, "- 42" ) + test_sng( "+###", -42, " -42" ) + test_sng( "+**#", +42, "*+42" ) + test_sng( "+**$#", -99, "*-$99" ) + + test_sng( "+**$##.##^^^^", -1234.56e+12, "-$1234.56E+12" ) + test_sng( "**$##.##^^^^+", -1234.56e+12, "$1234.56E+12-" ) + test_sng( "**$##.##^^^^-", 1234.56e+12, "$1234.56E+12 " ) + test_sng( "**$##.##+^^^^", -1234.56, "$1234.56-^^^^" ) + + test_sng( "#-", 1, "1 " ) + test_sng( "#^-", 1, "1^-" ) + test_sng( "#^^-", 1, "1^^-" ) + test_sng( "#^^^-", 1, "1E+0 " ) + test_sng( "#^^^^-", 1, "1E+00 " ) + test_sng( "#^^^^^-", 1, "1E+000 " ) + test_sng( "#^^^^^^-", 1, "1E+000^-" ) + + CLOSE_AND_TEST_FILE() + + END_TEST + + '' inf/nan/ind printing test + TEST( infnanindtest ) + + OPEN_FILE( "print_using_infnantest.txt" ) + + dim as single one = 1.0, zero = 0.0 + dim as single inf = one / zero + dim as single ind = inf - inf + dim as single nan = cvs(mki(&h7f800001)) + + dim as wstring * BUFFER_SIZE fmt = "+#.####" + + test_sng( fmt, inf, "+1.#INF" ) + test_sng( fmt, -inf, "-1.#INF" ) + + test_sng( fmt, nan, "+1.#NAN" ) + test_sng( fmt, -nan, "-1.#NAN" ) + + test_sng( fmt, ind, "-1.#IND" ) + + test_sng( "&", inf, "1.#INF" ) + test_sng( "&", -inf, "-1.#INF" ) + + test_sng( "&", ind, "-1.#IND" ) + test_sng( "#.####", ind, "%-1.#IND" ) + test_sng( "##.####", ind, "-1.#IND" ) + test_sng( "##.###", ind, "%-1.$00" ) + test_sng( "##.##", ind, "%-1.$0" ) + test_sng( "##.#", ind, "%-1.$" ) + test_sng( "##.", ind, "%-1." ) + test_sng( "##", ind, "%-1" ) + + CLOSE_AND_TEST_FILE() + + END_TEST + + '' wstring format test + TEST( strtest ) + + OPEN_FILE( "print_using_strtest.txt" ) + + dim i as integer, n as ulongint + + test_str( "&", "Test", "Test" ) + test_str( "!", "Test", "T" ) + test_str( "\\", "Test", "Te" ) + test_str( "\ \", "Test", "Tes" ) + test_str( "\ \", "Test", "Test" ) + test_str( "\ \", "Test", "Test " ) + + test_str( "!", "", " " ) + test_str( "\\", "", " " ) + test_str( "\ \", "", " " ) + + test_ll( "&", 0, "0" ) + + n = 1 + for i = 0 to 19 + + if n < 1.e+7 then + + test_ll( "&", n, str(n) ) + test_sng( "&", n, str(n) ) + + test_ll( "&", -n, "-" & n ) + + elseif n < 1.e+16 then + + test_ll( "&", n, str(n) ) + test_dbl( "&", n, str(n) ) + + test_ll( "&", -n, "-" & n ) + test_dbl( "&", -cdbl(n), "-" & n ) + + test_dbl( "&", -cdbl(n), "-" & n ) + + else + + test_ull( "&", n, str(n) ) + test_sng( "&", n, "1.E+" & i ) + + + if n < 1ull shl 63 then + test_ll( "&", -n, "-" & n ) + end if + test_sng( "&", -cdbl(n), "-1.E+" & i ) + + end if + + n *= 10 + + next i + + test_sng( "&", 1.0, "1" ) + test_sng( "&", 0.1, "0.1" ) + test_sng( "&", 0.01, "0.01" ) + test_sng( "&", 0.001, "0.001" ) + test_sng( "&", 0.0001, "1.E-4" ) + test_sng( "&", 0.00001, "1.E-5" ) + + test_sng( "&", 0.001234, "0.001234" ) + test_sng( "&", 0.0001234, "1.234E-4" ) + + test_sng( "&", 1.E+6, "1000000", 0 ) + test_sng( "&", 1.E+7, "1.E+7", 0 ) + test_dbl( "&", 1.E+15, "1" & wstring(15, asc("0")) ) + test_dbl( "&", 1.E+16, "1.E+16" ) + + test_sng( "&", 1.234E+6, "1234000", 0 ) + test_sng( "&", 1.234E+7, "1.234E+7", 0 ) + test_dbl( "&", 1.234E+15, "1234" & wstring(15-3, asc("0")) ) + test_dbl( "&", 1.234E+16, "1.234E+16" ) + + test_sng( "&", 1.E-9, "1.E-9", 0 ) + test_sng( "&", 1.E-10, "1.E-10", 0 ) + test_sng( "&", 1.E+9, "1.E+9", 0 ) + test_sng( "&", 1.E+10, "1.E+10", 0 ) + + test_dbl( "&", 1.E-99, "1.E-99" ) + test_dbl( "&", 1.E-100, "1.E-100" ) + test_dbl( "&", 1.E+99, "1.E+99" ) + test_dbl( "&", 1.E+100, "1.E+100" ) + + CLOSE_AND_TEST_FILE() + + END_TEST + + '' boolean test + TEST( booltest ) + + OPEN_FILE( "print_using_booltest.txt" ) + + test_bool("&", false, "false") + test_bool("&", true, "true") + + test_bool("+#", false, "+0") + test_bool("+#", true, "-1") + + test_bool("#", false, "0") + test_bool("#", true, "%-1") + + CLOSE_AND_TEST_FILE() + + END_TEST + +END_SUITE diff --git a/tests/wstring/write.bas b/tests/wstring/write.bas new file mode 100644 index 0000000000..9e886e1a79 --- /dev/null +++ b/tests/wstring/write.bas @@ -0,0 +1,138 @@ +#include "fbcunit.bi" + +#define PRINT_IF_UNEQUAL + +#define BUFFER_SIZE 50 + +#define QT(s) wstr("""" & wstr(s) & """") + +#define WWRITE( value, cmp ) _ + write #(1), value, cmp + +#macro OPEN_FILE( fn ) + const TESTFILE = ("./wstring/" & fn) + + open TESTFILE for output encoding "utf-16" as #1 +#endmacro + +#macro CLOSE_AND_TEST_FILE() + close #1 + + dim as wstring * BUFFER_SIZE sResult, sExpected + dim as integer errcount = 0 + open TESTFILE for input encoding "utf-16" as #1 + do until eof(1) + input #1, sResult, sExpected + if( sResult <> sExpected ) then +#ifdef PRINT_IF_UNEQUAL + print QT(sResult) & " <> " & QT(sExpected) + errcount += 1 +#endif + end if + CU_ASSERT_EQUAL( sResult, sExpected ) + loop + close #1 + + if errcount = 0 then + kill TESTFILE + end if +#endmacro + + +SUITE( fbc_tests.wstring_.write_ ) + + TEST( numbers ) + + #macro check( dtype, value ) + scope + dim x as dtype = value + dim cmp as wstring * BUFFER_SIZE = wstr( value ) + WWRITE( x, cmp ) + end scope + #endmacro + + OPEN_FILE( "write_numbers.txt" ) + + check( boolean, false ) + check( boolean, true ) + + check( byte, -128 ) + check( byte, -0 ) + check( byte, 127 ) + + check( ubyte, 0 ) + check( ubyte, 128 ) + check( ubyte, 255 ) + + check( short, -32768 ) + check( short, 0 ) + check( short, 32767 ) + + check( ushort, 0 ) + check( ushort, 32768 ) + check( ushort, 65535 ) + + check( long, -2147483648ll ) + check( long, 0 ) + check( long, 2147483647ull ) + + check( ulong, 0 ) + check( ulong, 2147483648ull ) + check( ulong, 4294967295ull ) + + check( longint, (-9223372036854775807ll-1ll) ) + check( longint, 0 ) + check( longint, 9223372036854775807ull ) + + check( ulongint, 0 ) + check( ulongint, 9223372036854775808ull ) + check( ulongint, 18446744073709551615ull ) + + check( single, -1.5 ) + check( single, -1.0 ) + check( single, -1.0 ) + check( single, -0.5 ) + check( single, 0.0 ) + check( single, 0.5 ) + check( single, 1.0) + check( single, 1.5 ) + check( single, 2.0 ) + check( single, 2.5 ) + + check( double, -1.5 ) + check( double, -1.0 ) + check( double, -1.0 ) + check( double, -0.5 ) + check( double, 0.0 ) + check( double, 0.5 ) + check( double, 1.0) + check( double, 1.5 ) + check( double, 2.0 ) + check( double, 2.5 ) + + CLOSE_AND_TEST_FILE() + + END_TEST + + TEST( strings ) + + #macro check( literal ) + scope + dim x as wstring * BUFFER_SIZE = literal + WWRITE( x, literal ) + end scope + #endmacro + + OPEN_FILE( "write_strings.txt" ) + + check( "" ) + check( " " ) + check( "0123456789" ) + check( "ABCDEFGHIJKLMNOP" ) + check( !"\u3041\u3043\u3045\u3047\u3049" ) + + CLOSE_AND_TEST_FILE() + + END_TEST + +END_SUITE