1 /// High-level wrappers for C-conversion functions.
2 module nxt.cconv;
3 
4 /// Returns: `value` as a `string`.
5 void toStringInSink(const double value,
6 					scope void delegate(scope const(char)[]) @safe sink,
7 					in uint digitCount = 5)
8 	@trusted
9 {
10 	static immutable digitCountMax = 61;
11 	assert(digitCount < digitCountMax);
12 	char[3 + digitCountMax] buffer; // (sign + dot + null) and digits
13 	gcvt(value, digitCount, buffer.ptr);
14 	import core.stdc.string : cstrlen = strlen;
15 	sink(buffer[0 .. cstrlen(buffer.ptr)]); /+ TODO: avoid +/
16 }
17 
18 /// Returns: `value` as a `string`.
19 string toString(const double value,
20 				in uint digitCount = 30)
21 	@trusted pure nothrow
22 {
23 	immutable length = 3 + digitCount; // (sign + dot + null) and digits
24 	auto buffer = new char[length];
25 	gcvt(value, digitCount, buffer.ptr);
26 	import core.stdc.string : cstrlen = strlen;
27 	return buffer[0 .. cstrlen(buffer.ptr)]; /+ TODO: avoid +/
28 }
29 
30 ///
31 pure nothrow @safe unittest {
32 	assert(0.0.toString(1) == `0`);
33 	assert(0.1.toString(2) == `0.1`);
34 
35 	assert((-1.0).toString(1) == `-1`);
36 	assert((-1.0).toString(2) == `-1`);
37 	assert((-1.0).toString(3) == `-1`);
38 
39 	assert(3.14.toString(3) == `3.14`);
40 	assert(3.141.toString(1) == `3`);
41 	assert(3.141.toString(2) == `3.1`);
42 	assert(3.141.toString(3) == `3.14`);
43 	assert(3.141.toString(4) == `3.141`);
44 	assert(3.141.toString(5) == `3.141`);
45 
46 	assert(1234567.123456789123456789.toString(7) == `1234567`);
47 	assert(1234567.123456789123456789.toString(8) == `1234567.1`);
48 	assert(1234567.123456789123456789.toString(9) == `1234567.12`);
49 	assert(1234567.123456789123456789.toString(20) == `1234567.1234567892`);
50 }
51 
52 private extern(C) pragma(inline, false) {
53 	pure nothrow @nogc:
54 	char *gcvt(double number, int ndigit, char *buf);
55 }