sprintf with Javascript
Category:
Last Updated: 2022/01/06 08:01:16
TIP
The latest version is published in the following Page.
This is sprintf
written by Javascript code.
/**
* php `sprintf` with Javascript
*
* Return a formatted string
* @see https://www.php.net/manual/en/function.sprintf.php
*
* @param string format
* @param mixed ...args
* @return string
*/
const sprintf = (format, ...args)=>{
const r = (()=>{
const uint_ = (n)=>{
try {
return BigInt.asUintN(64, BigInt(n))
} catch(e_) {
return n >= 0 ? n : ~n // not precise
}
}
const
b = (a)=>parseInt(a,10).toString(2),
c = (a)=>String.fromCharCode(parseInt(a, 10)),
d = (a)=>parseInt(a,10),
e = (a,p)=>parseFloat(a).toExponential(p > 0 ? p : 6),
E = (a,p)=>e.call(null,a,p).replace("e","E"),
f = (a,p)=>parseFloat(a).toFixed(p >= 0 ? p: 6),
F = (a,p)=>f.call(null,a,p),
g = (a,p,fn)=>{
p = p >= 0 ? Math.max(1, ~~p) : 6;
if (a < 1e-4 || Math.pow(10, p) <= a + 0.5) {
return String(e(a, p-1))
} else {
return String(parseFloat(a).toPrecision( p ))
}
},
G = (a,p)=>g(a,p).toUpperCase(),
h = (a,p)=>g(a,p),
H = (a,p)=>g(a,p).toUpperCase(),
o = (a,p)=>uint_(a).toString(8),
s = (a,p)=>p > 0 && a.length > p ? a.substr(0,p) : a,
u = (a)=>uint_(a),
x = (a)=>uint_(a).toString(16),
X = (a)=>x(a).toUpperCase();
return {b,c,d,e,E,f,F,g,G,h,H,o,s,u,x,X}
})();
//%[argnum$][flags][width][.precision]specifier.
let s = ""+format;
let index = 0;
s = s.replace(/\%((\d+)\$)?([\+\-]{0,2})?(0+|\x20|\'.)?(\d+)?(\.(\d+))?([l]?[^\s])/g,
function(match, argnum_,argnum, signs, char, width, precision_,precision,specifier) {
//console.log(arguments)
if (specifier == "%") return '%';
// specifier
if (specifier.length > 1 && specifier[0] == "l") specifier = specifier[1]; // l format is actually ignored in php sprintf.
if (! (specifier in r)) throw `undefined specifier: "${specifier}".`;
// argments
const idx = argnum ? argnum - 1 : index++;
if (args.length <= idx) throw `Too few arguments`
let a = args[idx]
// specifier
precision = typeof precision == "undefined" ? -1 : ~~precision
let ret = ""+r[specifier](a, precision);
// flags
// https://www.php.net/manual/en/function.sprintf.php
let minus_flg = false;
let plus_flg = false;
if (signs) {
if (signs.indexOf('+') >= 0) {
if ('deEfFgGhH'.indexOf(specifier) >= 0) {
if (a >= 0) {
plus_flg = true;
if (width) width--;
}
}
}
if (signs.indexOf('-') >= 0) {
minus_flg = true;
}
}
if (width && width > ret.length) {
if (! char && char !== "0") char = " ";
char = char[0] === "'" ? char[1] : char[0];
if (minus_flg == true && char == "0") {
if (specifier != "s" && ret.indexOf(".") < 0) {
char = " ";
}
}
if (minus_flg) {
ret += char.repeat(width - ret.length);
} else {
ret = char.repeat(width - ret.length) + ret;
}
}
if (plus_flg) {
ret = "+" + ret;
}
return ret
})
return s
}
module.exports = sprintf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
# Javascript Sprintf test Code with jest
const sprintf = require("/path/to/sprintf.js");
test("test sprintf()", ()=>{
// Testcases for some common usages
expect(sprintf("%d monkeys in the %s",5,"tree")).toBe("5 monkeys in the tree")
expect(sprintf("%2$d monkeys in the %1$s","tree",4)).toBe("4 monkeys in the tree")
// Testcases for each formats
expect(sprintf("%b",43951789)).toBe("10100111101010011010101101")
expect(sprintf("%c",65)).toBe("A")
expect(sprintf("%d",43951789)).toBe("43951789")
expect(sprintf("%e",43951789)).toBe("4.395179e+7")
expect(sprintf("%u",43951789)).toBe("43951789")
expect(sprintf("%u",-43951789)).toBe("18446744073665599827")
expect(sprintf("%u",-1)).toBe("18446744073709551615")
expect(sprintf("%f",43951789)).toBe("43951789.000000")
expect(sprintf("%o",43951789)).toBe("247523255")
expect(sprintf("%s",43951789)).toBe("43951789")
expect(sprintf("%x",43951789)).toBe("29ea6ad")
expect(sprintf("%X",43951789)).toBe("29EA6AD")
// "l" format is always ignored in php sprintf
expect(sprintf("%lb",43951789)).toBe("10100111101010011010101101")
expect(sprintf("%ld",43951789)).toBe("43951789")
expect(sprintf("%le",43951789)).toBe("4.395179e+7")
expect(sprintf("%lu",43951789)).toBe("43951789")
expect(sprintf("%lu",-43951789)).toBe("18446744073665599827")
expect(sprintf("%lu",-1)).toBe("18446744073709551615")
expect(sprintf("%lf",43951789)).toBe("43951789.000000")
expect(sprintf("%lo",43951789)).toBe("247523255")
expect(sprintf("%ls",43951789)).toBe("43951789") // l is ignored even with s
expect(sprintf("%lx",43951789)).toBe("29ea6ad")
expect(sprintf("%lX",43951789)).toBe("29EA6AD")
// Testcases for "+"
expect(sprintf("%+b",43951789)).toBe("10100111101010011010101101")
expect(sprintf("%+c",65)).toBe("A") // no "+" with chars or strings
expect(sprintf("%+d",43951789)).toBe("+43951789")
expect(sprintf("%+e",43951789)).toBe("+4.395179e+7")
expect(sprintf("%+u",43951789)).toBe("43951789")
expect(sprintf("%+u",-43951789)).toBe("18446744073665599827")
expect(sprintf("%+u",-1)).toBe("18446744073709551615")
expect(sprintf("%+f",43951789)).toBe("+43951789.000000")
expect(sprintf("%+o",43951789)).toBe("247523255")
expect(sprintf("%+s",43951789)).toBe("43951789")
expect(sprintf("%+x",43951789)).toBe("29ea6ad")
expect(sprintf("%+X",43951789)).toBe("29EA6AD")
// Testcases for numbers
expect(sprintf("%02d",1)).toBe("01")
expect(sprintf("%02.2f",1)).toBe("1.00")
expect(sprintf("%02.2f",1.1234)).toBe("1.12")
expect(sprintf("%06.2f",1.1234)).toBe("001.12")
// Testcases for numbers with general formats
expect(sprintf("%g",123.4567)).toBe("123.457")
expect(sprintf("%.5g",123.456)).toBe("123.46")
expect(sprintf("%.2g",1234500000000)).toBe("1.2e+12")
expect(sprintf("%.2g","123.45e+10")).toBe("1.2e+12")
expect(sprintf("%.2g",1.2345e-8)).toBe("1.2e-8")
expect(sprintf("%.2g","123.45e-10")).toBe("1.2e-8")
expect(sprintf("%.2G",1234500000000)).toBe("1.2E+12")
expect(sprintf("%.2G","123.45e+10")).toBe("1.2E+12")
expect(sprintf("%.2G",1.2345e-8)).toBe("1.2E-8")
expect(sprintf("%.2G","123.45e-10")).toBe("1.2E-8")
// Testcases for numbers with "+"
expect(sprintf("%+02d",1)).toBe("+1")
expect(sprintf("%+02.2f",1)).toBe("+1.00")
expect(sprintf("%+02.2f",1.1234)).toBe("+1.12")
expect(sprintf("%+06.2f",1.1234)).toBe("+01.12")
// Testcases for numbers with "+" and "-"
expect(sprintf("%-+02d",1)).toBe("+1")
expect(sprintf("%-+03d",1)).toBe("+1 ")
expect(sprintf("%-+02.2f",1)).toBe("+1.00")
expect(sprintf("%-+02.2f",1.1234)).toBe("+1.12")
expect(sprintf("%-+06.2f",1.1234)).toBe("+1.120")
// Testcases for string positions
expect(sprintf("[%s]","monkey")).toBe("[monkey]")
expect(sprintf("[%10s]","monkey")).toBe("[ monkey]")
expect(sprintf("[%-10s]","monkey")).toBe("[monkey ]")
expect(sprintf("[%010s]","monkey")).toBe("[0000monkey]")
expect(sprintf("[%'#10s]","monkey")).toBe("[####monkey]")
expect(sprintf("[%-010s]","monkey")).toBe("[monkey0000]")
expect(sprintf("[%-'#10s]","monkey")).toBe("[monkey####]")
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
# PHP Sprintf test Code with PHPUnit
I also prepared the PHPUnit
test for sprintf
in php
because I want to make sure that the return values are the same as or similar to those with Javascript sprintf.
<?php declare(strict_types=1);
use PHPUnit\Framework\TestCase;
final class SprintfTest extends TestCase {
public function testSprintf():void {
// Testcases for some common usages
$this->assertSame(sprintf('%d monkeys in the %s',5,'tree'), '5 monkeys in the tree');
$this->assertSame(sprintf('%2$d monkeys in the %1$s','tree',4), '4 monkeys in the tree');
// Testcases for each formats
$this->assertSame(sprintf('%b',43951789), '10100111101010011010101101');
$this->assertSame(sprintf('%c',65), 'A');
$this->assertSame(sprintf('%d',43951789), '43951789');
$this->assertSame(sprintf('%e',43951789), '4.395179e+7');
$this->assertSame(sprintf('%u',43951789), '43951789');
$this->assertSame(sprintf('%u',-43951789), '18446744073665599827');
$this->assertSame(sprintf('%u',-1), '18446744073709551615');
$this->assertSame(sprintf('%f',43951789), '43951789.000000');
$this->assertSame(sprintf('%o',43951789), '247523255');
$this->assertSame(sprintf('%s',43951789), '43951789');
$this->assertSame(sprintf('%x',43951789), '29ea6ad');
$this->assertSame(sprintf('%X',43951789), '29EA6AD');
// "l" format is always ignored in php sprintf
$this->assertSame(sprintf('%lb',43951789), '10100111101010011010101101');
$this->assertSame(sprintf('%ld',43951789), '43951789');
$this->assertSame(sprintf('%le',43951789), '4.395179e+7');
$this->assertSame(sprintf('%lu',43951789), '43951789');
$this->assertSame(sprintf('%lu',-43951789), '18446744073665599827');
$this->assertSame(sprintf('%lu',-1), '18446744073709551615');
$this->assertSame(sprintf('%lf',43951789), '43951789.000000');
$this->assertSame(sprintf('%lo',43951789), '247523255');
$this->assertSame(sprintf('%ls',43951789), '43951789'); // l is ignored even with s
$this->assertSame(sprintf('%lx',43951789), '29ea6ad');
$this->assertSame(sprintf('%lX',43951789), '29EA6AD');
// Testcases for "+"
$this->assertSame(sprintf('%+b',43951789), '10100111101010011010101101');
$this->assertSame(sprintf('%+c',65), 'A'); // no "+" with chars or strings
$this->assertSame(sprintf('%+d',43951789), '+43951789');
$this->assertSame(sprintf('%+e',43951789), '+4.395179e+7');
$this->assertSame(sprintf('%+u',43951789), '43951789');
$this->assertSame(sprintf('%+u',-43951789), '18446744073665599827');
$this->assertSame(sprintf('%+u',-1), '18446744073709551615');
$this->assertSame(sprintf('%+f',43951789), '+43951789.000000');
$this->assertSame(sprintf('%+o',43951789), '247523255');
$this->assertSame(sprintf('%+s',43951789), '43951789');
$this->assertSame(sprintf('%+x',43951789), '29ea6ad');
$this->assertSame(sprintf('%+X',43951789), '29EA6AD');
// Testcases for numbers
$this->assertSame(sprintf('%02d',1), '01');
$this->assertSame(sprintf('%02.2f',1), '1.00');
$this->assertSame(sprintf('%02.2f',1.1234), '1.12');
$this->assertSame(sprintf('%06.2f',1.1234), '001.12');
// Testcases for numbers with general formats
$this->assertSame(sprintf('%g',123.4567), '123.457');
$this->assertSame(sprintf('%.5g',123.456), '123.46');
$this->assertSame(sprintf('%.2g',1234500000000), '1.2e+12');
$this->assertSame(sprintf('%.2g','123.45e+10'), '1.2e+12');
$this->assertSame(sprintf('%.2g',1.2345e-8), '1.2e-8');
$this->assertSame(sprintf('%.2g','123.45e-10'), '1.2e-8');
$this->assertSame(sprintf('%.2G',1234500000000), '1.2E+12');
$this->assertSame(sprintf('%.2G','123.45e+10'), '1.2E+12');
$this->assertSame(sprintf('%.2G',1.2345e-8), '1.2E-8');
$this->assertSame(sprintf('%.2G','123.45e-10'), '1.2E-8');
// Testcases for numbers with "+"
$this->assertSame(sprintf('%+02d',1), '+1');
$this->assertSame(sprintf('%+02.2f',1), '+1.00');
$this->assertSame(sprintf('%+02.2f',1.1234), '+1.12');
$this->assertSame(sprintf('%+06.2f',1.1234), '+01.12');
// Testcases for numbers with "+" and "-"
$this->assertSame(sprintf('%-+02d',1), '+1');
$this->assertSame(sprintf('%-+03d',1), '+1 ');
$this->assertSame(sprintf('%-+02.2f',1), '+1.00');
$this->assertSame(sprintf('%-+02.2f',1.1234), '+1.12');
$this->assertSame(sprintf('%-+06.2f',1.1234), '+1.120');
// Testcases for string positions
$this->assertSame(sprintf('[%s]','monkey'), '[monkey]');
$this->assertSame(sprintf('[%10s]','monkey'), '[ monkey]');
$this->assertSame(sprintf('[%-10s]','monkey'), '[monkey ]');
$this->assertSame(sprintf('[%010s]','monkey'), '[0000monkey]');
$this->assertSame(sprintf('[%\'#10s]','monkey'), '[####monkey]');
$this->assertSame(sprintf('[%-010s]','monkey'), '[monkey0000]');
$this->assertSame(sprintf('[%-\'#10s]','monkey'), '[monkey####]');
}
}
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
Category:
Last Updated: 2022/01/06 08:01:16