214
|
1 // tries to implement a fairly complete variadic print function
|
|
2 module tangotests.vararg3;
|
|
3
|
|
4 extern(C) int printf(char*, ...);
|
|
5
|
|
6 struct User
|
|
7 {
|
|
8 char[] name;
|
|
9 char[] nick;
|
|
10 uint age;
|
|
11
|
|
12 char[] toString()
|
|
13 {
|
|
14 return nick ~ "(" ~ name ~ ")";
|
|
15 }
|
|
16 }
|
|
17
|
|
18 struct Infidel
|
|
19 {
|
|
20 char[] whocares;
|
|
21 }
|
|
22
|
|
23 class Obj
|
|
24 {
|
|
25 private char[] ty;
|
|
26
|
|
27 this(char[] t)
|
|
28 {
|
|
29 ty = t;
|
|
30 }
|
|
31
|
|
32 char[] toString()
|
|
33 {
|
|
34 return "Obj(" ~ ty ~ ")";
|
|
35 }
|
|
36 }
|
|
37
|
|
38 void main()
|
|
39 {
|
|
40 User user = User("Bob Doe", "bd", 47);
|
|
41 char[] str = user.toString();
|
|
42 printf("Direct call:\n%.*s\nBy typeinfo:\n", str.length, str.ptr);
|
|
43 print(user, '\n');
|
|
44
|
|
45 print("Without toString:\n");
|
|
46 Infidel inf = Infidel("not me");
|
|
47 print(inf, '\n');
|
|
48
|
|
49 print("Character arrays:\n");
|
|
50 print("hello world\n");
|
|
51
|
|
52 print("Signed integers:\n");
|
|
53 print(cast(byte)byte.max,' ',cast(short)short.max,' ',cast(int)int.max,' ',cast(long)long.max,'\n');
|
|
54
|
|
55 print("Unsigned integers:\n");
|
|
56 print(cast(ubyte)ubyte.max,' ',cast(ushort)ushort.max,' ',cast(uint)uint.max,' ',cast(ulong)ulong.max,'\n');
|
|
57
|
|
58 print("Floating point:\n");
|
|
59 print(cast(float)1.273f, ' ', cast(double)3.412367, ' ', cast(real)142.96731112, '\n');
|
|
60
|
|
61 print("Arrays:\n");
|
|
62 int[] ia1 = [1,2,3,4,5,6,7,8,9];
|
|
63 print(ia1, '\n');
|
|
64 float[] fa1 = [0.1f, 0.15f, 0.2f, 0.25f, 0.3f];
|
|
65 print(fa1, '\n');
|
|
66
|
|
67 print("Pointers:\n");
|
|
68 print(&user,'\n');
|
|
69 print(&inf,'\n');
|
|
70 print(&ia1,'\n');
|
|
71 print(&fa1,'\n');
|
|
72
|
|
73 print("Static arrays:\n");
|
|
74 int[5] isa1 = [1,2,4,8,16];
|
|
75 print(isa1,'\n');
|
|
76
|
|
77 print("Classes:\n");
|
|
78 Obj o = new Obj("foo");
|
|
79 print(o, '\n');
|
|
80
|
|
81 print("Mixed:\n");
|
|
82 print(123, ' ', 42.536f, " foobar ", ia1, ' ', user, '\n');
|
|
83 print(42, ' ', cast(byte)12, ' ', user, ' ', cast(short)1445, " foo\n");
|
|
84 }
|
|
85
|
|
86 private void* get_va_arg(TypeInfo ti, ref void* vp)
|
|
87 {
|
|
88 auto tisize = ti.tsize;
|
|
89 assert(tisize);
|
|
90 size_t size = tisize > size_t.sizeof ? size_t.sizeof : tisize;
|
|
91 void* vptmp = cast(void*)((cast(size_t)vp + size - 1) & ~(size - 1));
|
|
92 vp = vptmp + tisize;
|
|
93 return vptmp;
|
|
94 }
|
|
95
|
|
96 void print(TypeInfo ti, void* arg)
|
|
97 {
|
|
98 if (ti == typeid(byte))
|
|
99 printf("%d", *cast(byte*)arg);
|
|
100 else if (ti == typeid(short))
|
|
101 printf("%d", *cast(short*)arg);
|
|
102 else if (ti == typeid(int))
|
|
103 printf("%d", *cast(int*)arg);
|
|
104 else if (ti == typeid(long))
|
|
105 printf("%lld", *cast(long*)arg);
|
|
106
|
|
107 else if (ti == typeid(ubyte))
|
|
108 printf("%u", *cast(ubyte*)arg);
|
|
109 else if (ti == typeid(ushort))
|
|
110 printf("%u", *cast(ushort*)arg);
|
|
111 else if (ti == typeid(uint))
|
|
112 printf("%u", *cast(uint*)arg);
|
|
113 else if (ti == typeid(ulong))
|
|
114 printf("%llu", *cast(ulong*)arg);
|
|
115
|
|
116 else if (ti == typeid(float))
|
|
117 printf("%f", *cast(float*)arg);
|
|
118 else if (ti == typeid(double))
|
|
119 printf("%f", *cast(double*)arg);
|
|
120 else if (ti == typeid(real)) // FIXME: 80bit?
|
|
121 printf("%f", *cast(real*)arg);
|
|
122
|
|
123 else if (ti == typeid(char))
|
|
124 printf("%.*s", 1, arg);
|
|
125 else if (ti == typeid(wchar))
|
|
126 printf("%.*s", 2, arg);
|
|
127 else if (ti == typeid(dchar))
|
|
128 printf("%.*s", 4, arg);
|
|
129
|
|
130 else if (ti == typeid(char[]))
|
|
131 {
|
|
132 char[] str = *cast(char[]*)arg;
|
|
133 printf("%.*s", str.length, str.ptr);
|
|
134 }
|
|
135 else if (ti == typeid(wchar[]))
|
|
136 {
|
|
137 wchar[] str = *cast(wchar[]*)arg;
|
|
138 printf("%.*s", str.length*2, str.ptr);
|
|
139 }
|
|
140 else if (ti == typeid(dchar[]))
|
|
141 {
|
|
142 dchar[] str = *cast(dchar[]*)arg;
|
|
143 printf("%.*s", str.length*4, str.ptr);
|
|
144 }
|
|
145
|
|
146 else if (auto pti = cast(TypeInfo_Pointer)ti)
|
|
147 {
|
|
148 printf("%p", *cast(void**)arg);
|
|
149 }
|
|
150
|
|
151 else if (auto sti = cast(TypeInfo_Struct)ti)
|
|
152 {
|
|
153 if (sti.xtoString !is null)
|
|
154 {
|
|
155 char[] str = sti.xtoString(arg);
|
|
156 printf("%.*s", str.length, str.ptr);
|
|
157 }
|
|
158 else
|
|
159 {
|
|
160 char[] str = sti.toString();
|
|
161 printf("%.*s", str.length, str.ptr);
|
|
162 }
|
|
163 }
|
|
164
|
|
165 else if (auto ati = cast(TypeInfo_Array)ti)
|
|
166 {
|
|
167 auto tnext = ati.next;
|
|
168 size_t len = *cast(size_t*)arg;
|
|
169 void* ptr = *(cast(void**)arg + 1);
|
|
170 printf("[");
|
|
171 for(auto i=0; i<len; ++i)
|
|
172 {
|
|
173 print(tnext, get_va_arg(tnext, ptr));
|
|
174 if (i < len-1)
|
|
175 printf(",");
|
|
176 }
|
|
177 printf("]");
|
|
178 }
|
|
179
|
|
180 else if (auto cti = cast(TypeInfo_Class)ti)
|
|
181 {
|
|
182 auto o = *cast(Object*)arg;
|
|
183 char[] str = o.toString();
|
|
184 printf("%.*s", str.length, str.ptr);
|
|
185 }
|
|
186
|
|
187 // static arrays are converted to dynamic arrays when passed to variadic functions
|
|
188 else if (auto sati = cast(TypeInfo_StaticArray)ti)
|
|
189 {
|
|
190 assert(0, "static arrays not supported");
|
|
191 }
|
|
192
|
|
193 else if (auto aati = cast(TypeInfo_AssociativeArray)ti)
|
|
194 {
|
|
195 assert(0, "associative array not supported");
|
|
196 }
|
|
197
|
|
198 else
|
|
199 {
|
|
200 char[] str = ti.toString();
|
|
201 printf("typeinfo: %.*s\n", str.length, str.ptr);
|
|
202 str = ti.classinfo.name;
|
|
203 printf("typeinfo.classinfo: %.*s\n", str.length, str.ptr);
|
|
204 assert(0, "unsupported type ^");
|
|
205 }
|
|
206 }
|
|
207
|
|
208 void print(...)
|
|
209 {
|
|
210 void* argptr = _argptr;
|
|
211 assert(argptr);
|
|
212
|
|
213 foreach(i,ti; _arguments)
|
|
214 {
|
|
215 void* arg = get_va_arg(ti, argptr);
|
|
216 assert(arg);
|
|
217 print(ti, arg);
|
|
218 }
|
|
219 }
|