1 /// Module to replace std.stdio write functions to @nogc ones 2 module mutils.stdio; 3 4 import core.stdc.stdio : fwrite, printf, stdout; 5 import std.meta : aliasSeqOf; 6 import std.traits; 7 8 import mutils.conv; 9 10 static char[1024] gTmpStdioStrBuff; // Own buffer to be independant from mutils.conv 11 12 /** 13 * Writes string to stdout 14 * Compared to std.stdio.writeln this writeln is not using GC, can print @disable this() structs, can print core.simd.vector's 15 * write is not pure but we will pretend it is to enable write debug 16 **/ 17 void write(T...)(auto ref const T el) @trusted { 18 static void writeImpl(EL)(auto ref const EL el) { 19 string elStr = to!(string)(el, gTmpStdioStrBuff[]); 20 fwrite(elStr.ptr, 1, elStr.length, stdout); 21 } 22 23 static auto assumePure(DG)(scope DG t) 24 if (isFunctionPointer!DG || isDelegate!DG) { 25 enum attrs = functionAttributes!DG | FunctionAttribute.pure_; 26 return cast(SetFunctionAttributes!(DG, functionLinkage!DG, attrs)) t; 27 } 28 29 assumePure(() => writeImpl(el[0]))(); 30 static if (T.length > 1) { 31 write(el[1 .. $]); 32 } 33 } 34 35 /// Like write but adds new line at end 36 void writeln(T...)(auto ref const T el) { 37 write(el, "\n"); 38 } 39 40 /// Like writeln but adds space beetwen arguments 41 void writelns(T...)(auto ref const T el) { 42 foreach (e; el) { 43 write(e, ' '); 44 } 45 write("\n"); 46 } 47 48 /// Writes format to stdout changing %s to proper argument 49 /// Only %s is supported, it is not printf 50 void writefln(T...)(string format, auto ref const T el) { 51 alias indices = aliasSeqOf!([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 123]); 52 int lastEnd = 0; 53 int elementsWritten = 0; 54 for (int i = 0; i < format.length; i++) { 55 char c = format[i]; 56 if (c != '%') { 57 continue; 58 } 59 assert(format[i + 1] == 's'); // Only %s is supported 60 write(format[lastEnd .. i]); 61 lastEnd = i + 2; 62 sw: 63 switch (elementsWritten) { 64 foreach (elNum; indices[0 .. el.length]) { 65 case elNum: 66 write(el[elNum]); 67 break sw; 68 } 69 default: 70 assert(0, "Wrong number of specifiers and parameters"); 71 } 72 73 elementsWritten++; 74 75 } 76 write("\n"); 77 } 78 79 private struct TestStruct { 80 @nogc nothrow @safe pure: 81 @disable this(); 82 @disable this(this); 83 84 this(int i) { 85 } 86 87 int a; 88 double c; 89 } 90 91 // Function because we dont want to prit something during tests 92 private void testMutilsStdio() @nogc nothrow @safe pure { 93 TestStruct w = TestStruct(3); 94 writeln(true); 95 writeln(false); 96 write("__text__ "); 97 writeln(w, " <- this is struct"); 98 // arrays 99 int[9] arr = [1, 2, 3, 4, 5, 6, 7, 8, 9]; 100 writeln(arr[]); 101 writeln(arr); 102 version (X86_64) { 103 // simd 104 import core.simd; 105 106 ubyte16 vec = 14; 107 writeln(vec); 108 } 109 // writeln spaced 110 writelns(1, 2, 3, 4, 5, 6, 7, 8, 9); 111 // writefln 112 writefln("%s <- this is something | and this is something -> %s", w, 1); 113 // writeln empty 114 writeln(); 115 } 116 117 unittest { 118 //testMutilsStdio(); 119 }