summaryrefslogtreecommitdiffhomepage
path: root/tests/custom/03_stdlib/28_printf
diff options
context:
space:
mode:
Diffstat (limited to 'tests/custom/03_stdlib/28_printf')
-rw-r--r--tests/custom/03_stdlib/28_printf526
1 files changed, 526 insertions, 0 deletions
diff --git a/tests/custom/03_stdlib/28_printf b/tests/custom/03_stdlib/28_printf
new file mode 100644
index 0000000..a2a6d27
--- /dev/null
+++ b/tests/custom/03_stdlib/28_printf
@@ -0,0 +1,526 @@
+The `printf()` function formats given input value according to a format
+string specified as first argument. The format string mimicks the syntax
+and directives used by C printf().
+
+Each directive (with the exception of %%) in the format string expects
+a corresponding argument. If fewer arguments are passed to printf() than
+required by the format string, missing values will be assumed to be `null`
+and be interpreted accordingly. Excess arguments are ignored.
+
+Writes the output string formatted according to the format string with all
+format directives interpolated by their respective values to the standard
+output stream of the VM.
+
+Returns the number of bytes written to the output stream.
+
+Writes an empty string in case the format string argument is not a valid
+string value.
+
+-- Testcase --
+{%
+ // String interpolation, corresponding value will be converted
+ // into string if needed.
+ printf("Hello %s!\n", "World");
+ printf("Hello %s!\n", false);
+ printf("Hello %s!\n", 123);
+ printf("Hello %s!\n", null);
+ printf("Hello %s!\n");
+
+ // Signed integer interpolation, corresponding value will be
+ // converted into integer if needed. Also `d` and `i` are aliases.
+ printf("%d\n", 123);
+ printf("%i\n", 456.789);
+ printf("%d\n", true);
+ printf("%d\n", "0x42");
+ printf("%d\n", "invalid");
+ printf("%d\n", null);
+ printf("%d\n", 0xffffffffffffffff);
+ printf("%d\n");
+
+ // Unsigned integer interpolation in decimal notation, corresponding
+ // value will be converted into unsigned integer if needed.
+ printf("%u\n", 123);
+ printf("%u\n", -123);
+ printf("%u\n", 0xffffffffffffffff);
+ printf("%u\n", 456.789);
+ printf("%u\n", "invalid");
+ printf("%u\n", null);
+ printf("%u\n");
+
+ // Unsigned integer interpolation in octal notation, corresponding
+ // value will be converted into unsigned integer if needed.
+ printf("%o\n", 123);
+ printf("%o\n", -123);
+ printf("%o\n", 0xffffffffffffffff);
+ printf("%o\n", 456.789);
+ printf("%o\n", "invalid");
+ printf("%o\n", null);
+ printf("%o\n");
+
+ // Unsigned integer interpolation in lower case hexadecimal notation,
+ // corresponding value will be converted into unsigned integer if
+ // needed.
+ printf("%x\n", 123);
+ printf("%x\n", -123);
+ printf("%x\n", 0xffffffffffffffff);
+ printf("%x\n", 456.789);
+ printf("%x\n", "invalid");
+ printf("%x\n", null);
+ printf("%x\n");
+
+ // Unsigned integer interpolation in upper case hexadecimal notation,
+ // corresponding value will be converted into unsigned integer if
+ // needed.
+ printf("%X\n", 123);
+ printf("%X\n", -123);
+ printf("%X\n", 0xffffffffffffffff);
+ printf("%X\n", 456.789);
+ printf("%X\n", "invalid");
+ printf("%X\n", null);
+ printf("%X\n");
+
+ // Floating point value interpolation in exponential notation,
+ // corresponding value will be converted to double if needed.
+ printf("%e\n", 123);
+ printf("%e\n", -123);
+ printf("%e\n", 456.789);
+ printf("%e\n", -456.789);
+ printf("%e\n", "invalid");
+ printf("%e\n", null);
+ printf("%e\n");
+
+ // Floating point value interpolation in exponential notation,
+ // using uppercase characters. Corresponding value will be converted
+ // to double if needed.
+ printf("%E\n", 123);
+ printf("%E\n", -123);
+ printf("%E\n", 456.789);
+ printf("%E\n", -456.789);
+ printf("%E\n", "invalid");
+ printf("%E\n", null);
+ printf("%E\n");
+
+ // Floating point value interpolation in decimal point notation,
+ // corresponding value will be converted to double if needed.
+ printf("%f\n", 123);
+ printf("%f\n", -123);
+ printf("%f\n", 456.789);
+ printf("%f\n", -456.789);
+ printf("%f\n", "invalid");
+ printf("%f\n", null);
+ printf("%f\n");
+
+ // Floating point value interpolation in decimal point notation,
+ // using uppercase characters. Corresponding value will be converted
+ // to double if needed.
+ printf("%F\n", 123);
+ printf("%F\n", -123);
+ printf("%F\n", 456.789);
+ printf("%F\n", -456.789);
+ printf("%F\n", "invalid");
+ printf("%F\n", null);
+ printf("%F\n");
+
+ // Floating point value interpolation in either decimal point or
+ // exponential notation, depending on size of exponent. Corresponding
+ // value will be converted to double if needed.
+ printf("%g\n", 123.456);
+ printf("%g\n", 0.0000001);
+ printf("%g\n", "invalid");
+
+ // Floating point value interpolation in either decimal point or
+ // exponential notation, depending on size of exponent and using
+ // uppercase characters. Corresponding value will be converted to
+ // double if needed.
+ printf("%G\n", 123.456);
+ printf("%G\n", 0.0000001);
+ printf("%G\n", "invalid");
+
+ // Character interpolation. The corresponding value is casted as `char`
+ // and the resulting character is interpolated.
+ printf("%c\n", 65);
+ //printf("%c\n", -1);
+ //printf("%c\n", 456.789);
+ //printf("%c\n", "invalid");
+
+ // JSON interpolation. The corresponding value is JSON encoded and
+ // interpolated as string.
+ printf("%J\n", "Hello\n");
+ printf("%J\n", 123);
+ printf("%J\n", [ 1, 2, 3 ]);
+ printf("%J\n", { some: "dictionary", an: [ "array", true, false ] });
+ printf("%J\n", null);
+ printf("%J\n");
+
+ // Escaping `%`. The `%%` format string will produce a literal `%`.
+ // No corresponding argument is expected.
+ printf("%%\n");
+%}
+-- End --
+
+-- Expect stdout --
+Hello World!
+Hello false!
+Hello 123!
+Hello (null)!
+Hello (null)!
+123
+456
+1
+66
+0
+0
+-1
+0
+123
+18446744073709551493
+18446744073709551615
+456
+0
+0
+0
+173
+1777777777777777777605
+1777777777777777777777
+710
+0
+0
+0
+7b
+ffffffffffffff85
+ffffffffffffffff
+1c8
+0
+0
+0
+7B
+FFFFFFFFFFFFFF85
+FFFFFFFFFFFFFFFF
+1C8
+0
+0
+0
+1.230000e+02
+-1.230000e+02
+4.567890e+02
+-4.567890e+02
+nan
+0.000000e+00
+0.000000e+00
+1.230000E+02
+-1.230000E+02
+4.567890E+02
+-4.567890E+02
+NAN
+0.000000E+00
+0.000000E+00
+123.000000
+-123.000000
+456.789000
+-456.789000
+nan
+0.000000
+0.000000
+123.000000
+-123.000000
+456.789000
+-456.789000
+NAN
+0.000000
+0.000000
+123.456
+1e-07
+nan
+123.456
+1E-07
+NAN
+A
+"Hello\n"
+123
+[ 1, 2, 3 ]
+{ "some": "dictionary", "an": [ "array", true, false ] }
+null
+null
+%
+-- End --
+
+
+Field widths may be specified for format directives.
+
+-- Testcase --
+{%
+ // by default the output of a format directive is as long as the
+ // string representation of the corresponding value
+ printf("[%s]\n", "test");
+
+ // by specifying a field width, the output will be padded to the
+ // given length
+ printf("[%10s]\n", "test");
+
+ // the same applies to numbers
+ printf("[%10d]\n", 123);
+ printf("[%10f]\n", 1.0);
+
+ // and to char formats
+ printf("[%10c]\n", 65);
+
+ // field width is not applicable to `%` formats
+ printf("[%10%]\n");
+%}
+-- End --
+
+-- Expect stdout --
+[test]
+[ test]
+[ 123]
+[ 1.000000]
+[ A]
+[%]
+-- End --
+
+
+Precisions may be specified for format directives.
+
+-- Testcase --
+{%
+ // For `f`, `F`, `e` and `E`, the precision specifies the amount of
+ // digits after the comma
+ printf("[%.3f]\n", 1/3);
+ printf("[%.3F]\n", 1/3);
+ printf("[%.3e]\n", 1/3);
+ printf("[%.3E]\n", 1/3);
+
+ // For `g` and `G` the precision specifies the number of significant
+ // digits to print before switching to exponential notation
+ printf("[%.3g]\n", 1000.1);
+ printf("[%.3G]\n", 1000.1);
+
+ // For strings, the precision specifies the amount of characters to
+ // print at most
+ printf("[%.5s]\n", "test");
+ printf("[%.3s]\n", "test");
+
+ // For JSON format, the precision specifies the amount of indentation
+ // to use. Omitting precision will not indent, specifying a precision
+ // of `0` uses tabs for indentation, any other precision uses this
+ // many spaces
+ printf("<%J>\n", [ 1, 2, 3, { true: false } ]), // no indent
+ printf("<%.J>\n", [ 1, 2, 3, { true: false } ]), // tab indent
+ printf("<%.0J>\n", [ 1, 2, 3, { true: false } ]), // tab indent
+ printf("<%.1J>\n", [ 1, 2, 3, { true: false } ]), // indent using one space
+ printf("<%.4J>\n", [ 1, 2, 3, { true: false } ]), // indent using four spaces
+
+ // precision does not apply to char, integer or `%` formats
+ printf("[%.3d]\n", 1000);
+ printf("[%.3c]\n", 65);
+ printf("[%.3%]\n");
+%}
+-- End --
+
+-- Expect stdout --
+[0.000]
+[0.000]
+[0.000e+00]
+[0.000E+00]
+[1e+03]
+[1E+03]
+[test]
+[tes]
+<[ 1, 2, 3, { "true": false } ]>
+<[
+ 1,
+ 2,
+ 3,
+ {
+ "true": false
+ }
+]>
+<[
+ 1,
+ 2,
+ 3,
+ {
+ "true": false
+ }
+]>
+<[
+ 1,
+ 2,
+ 3,
+ {
+ "true": false
+ }
+]>
+<[
+ 1,
+ 2,
+ 3,
+ {
+ "true": false
+ }
+]>
+[1000]
+[A]
+[%]
+-- End --
+
+
+A number of flag characters are supported for format directives.
+
+-- Testcase --
+{%
+ // The recognized flag characters are `#`, `0`, `-`, `+` and ` ` (space)
+ printf("%#0+- s\n", "test");
+
+ // Repetitions of flag characters are accepted
+ printf("%###s\n", "test");
+ printf("%000s\n", "test");
+ printf("%++-s\n", "test");
+ printf("%-- s\n", "test");
+ printf("% s\n", "test");
+
+ // The `#` flag produces alternative forms of various conversions
+ printf("%o / %#o\n", 15, 15);
+ printf("%x / %#x\n", 16, 16);
+ printf("%X / %#X\n", 17, 17);
+ printf("%g / %#g\n", 1.0, 1.0);
+
+ // The `0` flag indicates zero- instead of space-padding for various
+ // numeric conversions.
+ printf("[%5d / %05d]\n", -10, -10);
+ printf("[%5d / %05d]\n", 11, 11);
+ printf("[%5g / %05g]\n", -12.0, -12.0);
+ printf("[%5g / %05g]\n", 13.0, 13.0);
+ printf("[%5s / %05s]\n", "a", "a");
+
+ // The `-` flag indicates left, instead of right padding. It will
+ // override `0` and always pad with spaces
+ printf("[%-5d / %-05d]\n", -10, -10);
+ printf("[%-5d / %-05d]\n", 11, 11);
+ printf("[%-5g / %-05g]\n", -12.0, -12.0);
+ printf("[%-5g / %-05g]\n", 13.0, 13.0);
+ printf("[%-5s / %-05s]\n", "a", "a");
+
+ // The `+` flag indicates that a sign (`+` or `-`) should be placed
+ // before signed numeric values. It overrides ` ` (space).
+ printf("[%+5d / %+05d]\n", -10, -10);
+ printf("[%+5d / %+05d]\n", 11, 11);
+ printf("[%+5g / %+05g]\n", -12.0, -12.0);
+ printf("[%+5g / %+05g]\n", 13.0, 13.0);
+ printf("[%+5s / %+05s]\n", "a", "a");
+
+ // The ` ` (space) flag indicates that a blank should be placed
+ // before positive numbers (useful to ensure that negative and
+ // positive values in output are aligned)
+ printf("[%-5d / %- 5d]\n", -10, -10);
+ printf("[%-5d / %- 5d]\n", 11, 11);
+ printf("[%-5g / %- 5g]\n", -12.0, -12.0);
+ printf("[%-5g / %- 5g]\n", 13.0, 13.0);
+ printf("[%-5s / %- 5s]\n", "a", "a");
+%}
+-- End --
+
+-- Expect stdout --
+test
+test
+test
+test
+test
+test
+17 / 017
+10 / 0x10
+11 / 0X11
+1 / 1.00000
+[ -10 / -0010]
+[ 11 / 00011]
+[ -12 / -0012]
+[ 13 / 00013]
+[ a / a]
+[-10 / -10 ]
+[11 / 11 ]
+[-12 / -12 ]
+[13 / 13 ]
+[a / a ]
+[ -10 / -0010]
+[ +11 / +0011]
+[ -12 / -0012]
+[ +13 / +0013]
+[ a / a]
+[-10 / -10 ]
+[11 / 11 ]
+[-12 / -12 ]
+[13 / 13 ]
+[a / a ]
+-- End --
+
+
+Unrecognized format directives are copied to the output string as-is.
+
+-- Testcase --
+{%
+ // A truncated format directive is preserved
+ printf("test %\n", "test");
+ printf("test %-010.3\n", "test");
+
+ // An unrecognized format directive is preserved
+ printf("test %y test\n", 123);
+ printf("test %~123s test\n", 123);
+%}
+-- End --
+
+-- Expect stdout --
+test %
+test %-010.3
+test %y test
+test %~123s test
+-- End --
+
+
+Missing values for format directives are treated as `null`.
+
+-- Testcase --
+{%
+ printf("%s\n");
+ printf("%d\n");
+ printf("%u\n");
+ printf("%o\n");
+ printf("%x\n");
+ printf("%X\n");
+ printf("%f\n");
+ printf("%F\n");
+ printf("%e\n");
+ printf("%E\n");
+ printf("%g\n");
+ printf("%G\n");
+ //printf("%c\n");
+ printf("%J\n");
+%}
+-- End --
+
+-- Expect stdout --
+(null)
+0
+0
+0
+0
+0
+0.000000
+0.000000
+0.000000e+00
+0.000000E+00
+0
+0
+null
+-- End --
+
+
+Supplying a non-string format value will yield an empty string result.
+
+-- Testcase --
+{%
+ printf(true, 1, 2, 3);
+%}
+-- End --
+
+-- Expect stdout --
+-- End --