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 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 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 @safe pure nothrow unittest 32 { 33 assert(0.0.toString(1) == `0`); 34 assert(0.1.toString(2) == `0.1`); 35 36 assert((-1.0).toString(1) == `-1`); 37 assert((-1.0).toString(2) == `-1`); 38 assert((-1.0).toString(3) == `-1`); 39 40 assert(3.14.toString(3) == `3.14`); 41 assert(3.141.toString(1) == `3`); 42 assert(3.141.toString(2) == `3.1`); 43 assert(3.141.toString(3) == `3.14`); 44 assert(3.141.toString(4) == `3.141`); 45 assert(3.141.toString(5) == `3.141`); 46 47 assert(1234567.123456789123456789.toString(7) == `1234567`); 48 assert(1234567.123456789123456789.toString(8) == `1234567.1`); 49 assert(1234567.123456789123456789.toString(9) == `1234567.12`); 50 assert(1234567.123456789123456789.toString(20) == `1234567.1234567892`); 51 } 52 53 private extern(C) pragma(inline, false) 54 { 55 pure nothrow @nogc: 56 char *gcvt(double number, int ndigit, char *buf); 57 }