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