1/// @ref gtx_string_cast
2/// @file glm/gtx/string_cast.inl
3
4#include <cstdarg>
5#include <cstdio>
6
7namespace glm{
8namespace detail
9{
10	GLM_FUNC_QUALIFIER std::string format(const char* msg, ...)
11	{
12		std::size_t const STRING_BUFFER(4096);
13		char text[STRING_BUFFER];
14		va_list list;
15
16		if(msg == 0)
17			return std::string();
18
19		va_start(list, msg);
20#		if(GLM_COMPILER & GLM_COMPILER_VC)
21			vsprintf_s(text, STRING_BUFFER, msg, list);
22#		else//
23			vsprintf(text, msg, list);
24#		endif//
25		va_end(list);
26
27		return std::string(text);
28	}
29
30	static const char* LabelTrue = "true";
31	static const char* LabelFalse = "false";
32
33	template <typename T, bool isFloat = false>
34	struct literal
35	{
36		GLM_FUNC_QUALIFIER static char const * value() {return "%d";};
37	};
38
39	template <typename T>
40	struct literal<T, true>
41	{
42		GLM_FUNC_QUALIFIER static char const * value() {return "%f";};
43	};
44
45#	if GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC
46	template <>
47	struct literal<uint64_t, false>
48	{
49		GLM_FUNC_QUALIFIER static char const * value() {return "%lld";};
50	};
51
52	template <>
53	struct literal<int64_t, false>
54	{
55		GLM_FUNC_QUALIFIER static char const * value() {return "%lld";};
56	};
57#	endif//GLM_MODEL == GLM_MODEL_32 && GLM_COMPILER && GLM_COMPILER_VC
58
59	template <typename T>
60	struct prefix{};
61
62	template <>
63	struct prefix<float>
64	{
65		GLM_FUNC_QUALIFIER static char const * value() {return "";};
66	};
67
68	template <>
69	struct prefix<double>
70	{
71		GLM_FUNC_QUALIFIER static char const * value() {return "d";};
72	};
73
74	template <>
75	struct prefix<bool>
76	{
77		GLM_FUNC_QUALIFIER static char const * value() {return "b";};
78	};
79
80	template <>
81	struct prefix<uint8_t>
82	{
83		GLM_FUNC_QUALIFIER static char const * value() {return "u8";};
84	};
85
86	template <>
87	struct prefix<int8_t>
88	{
89		GLM_FUNC_QUALIFIER static char const * value() {return "i8";};
90	};
91
92	template <>
93	struct prefix<uint16_t>
94	{
95		GLM_FUNC_QUALIFIER static char const * value() {return "u16";};
96	};
97
98	template <>
99	struct prefix<int16_t>
100	{
101		GLM_FUNC_QUALIFIER static char const * value() {return "i16";};
102	};
103
104	template <>
105	struct prefix<uint32_t>
106	{
107		GLM_FUNC_QUALIFIER static char const * value() {return "u";};
108	};
109
110	template <>
111	struct prefix<int32_t>
112	{
113		GLM_FUNC_QUALIFIER static char const * value() {return "i";};
114	};
115
116	template <>
117	struct prefix<uint64_t>
118	{
119		GLM_FUNC_QUALIFIER static char const * value() {return "u64";};
120	};
121
122	template <>
123	struct prefix<int64_t>
124	{
125		GLM_FUNC_QUALIFIER static char const * value() {return "i64";};
126	};
127
128	template <template <typename, precision> class matType, typename T, precision P>
129	struct compute_to_string
130	{};
131
132	template <precision P>
133	struct compute_to_string<tvec1, bool, P>
134	{
135		GLM_FUNC_QUALIFIER static std::string call(tvec1<bool, P> const & x)
136		{
137			return detail::format("bvec1(%s)",
138				x[0] ? detail::LabelTrue : detail::LabelFalse);
139		}
140	};
141
142	template <precision P>
143	struct compute_to_string<tvec2, bool, P>
144	{
145		GLM_FUNC_QUALIFIER static std::string call(tvec2<bool, P> const & x)
146		{
147			return detail::format("bvec2(%s, %s)",
148				x[0] ? detail::LabelTrue : detail::LabelFalse,
149				x[1] ? detail::LabelTrue : detail::LabelFalse);
150		}
151	};
152
153	template <precision P>
154	struct compute_to_string<tvec3, bool, P>
155	{
156		GLM_FUNC_QUALIFIER static std::string call(tvec3<bool, P> const & x)
157		{
158			return detail::format("bvec3(%s, %s, %s)",
159				x[0] ? detail::LabelTrue : detail::LabelFalse,
160				x[1] ? detail::LabelTrue : detail::LabelFalse,
161				x[2] ? detail::LabelTrue : detail::LabelFalse);
162		}
163	};
164
165	template <precision P>
166	struct compute_to_string<tvec4, bool, P>
167	{
168		GLM_FUNC_QUALIFIER static std::string call(tvec4<bool, P> const & x)
169		{
170			return detail::format("bvec4(%s, %s, %s, %s)",
171				x[0] ? detail::LabelTrue : detail::LabelFalse,
172				x[1] ? detail::LabelTrue : detail::LabelFalse,
173				x[2] ? detail::LabelTrue : detail::LabelFalse,
174				x[3] ? detail::LabelTrue : detail::LabelFalse);
175		}
176	};
177
178	template <typename T, precision P>
179	struct compute_to_string<tvec1, T, P>
180	{
181		GLM_FUNC_QUALIFIER static std::string call(tvec1<T, P> const & x)
182		{
183			char const * PrefixStr = prefix<T>::value();
184			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
185			std::string FormatStr(detail::format("%svec1(%s)",
186				PrefixStr,
187				LiteralStr));
188
189			return detail::format(FormatStr.c_str(), x[0]);
190		}
191	};
192
193	template <typename T, precision P>
194	struct compute_to_string<tvec2, T, P>
195	{
196		GLM_FUNC_QUALIFIER static std::string call(tvec2<T, P> const & x)
197		{
198			char const * PrefixStr = prefix<T>::value();
199			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
200			std::string FormatStr(detail::format("%svec2(%s, %s)",
201				PrefixStr,
202				LiteralStr, LiteralStr));
203
204			return detail::format(FormatStr.c_str(), x[0], x[1]);
205		}
206	};
207
208	template <typename T, precision P>
209	struct compute_to_string<tvec3, T, P>
210	{
211		GLM_FUNC_QUALIFIER static std::string call(tvec3<T, P> const & x)
212		{
213			char const * PrefixStr = prefix<T>::value();
214			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
215			std::string FormatStr(detail::format("%svec3(%s, %s, %s)",
216				PrefixStr,
217				LiteralStr, LiteralStr, LiteralStr));
218
219			return detail::format(FormatStr.c_str(), x[0], x[1], x[2]);
220		}
221	};
222
223	template <typename T, precision P>
224	struct compute_to_string<tvec4, T, P>
225	{
226		GLM_FUNC_QUALIFIER static std::string call(tvec4<T, P> const & x)
227		{
228			char const * PrefixStr = prefix<T>::value();
229			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
230			std::string FormatStr(detail::format("%svec4(%s, %s, %s, %s)",
231				PrefixStr,
232				LiteralStr, LiteralStr, LiteralStr, LiteralStr));
233
234			return detail::format(FormatStr.c_str(), x[0], x[1], x[2], x[3]);
235		}
236	};
237
238
239	template <typename T, precision P>
240	struct compute_to_string<tmat2x2, T, P>
241	{
242		GLM_FUNC_QUALIFIER static std::string call(tmat2x2<T, P> const & x)
243		{
244			char const * PrefixStr = prefix<T>::value();
245			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
246			std::string FormatStr(detail::format("%smat2x2((%s, %s), (%s, %s))",
247				PrefixStr,
248				LiteralStr, LiteralStr,
249				LiteralStr, LiteralStr));
250
251			return detail::format(FormatStr.c_str(),
252				x[0][0], x[0][1],
253				x[1][0], x[1][1]);
254		}
255	};
256
257	template <typename T, precision P>
258	struct compute_to_string<tmat2x3, T, P>
259	{
260		GLM_FUNC_QUALIFIER static std::string call(tmat2x3<T, P> const & x)
261		{
262			char const * PrefixStr = prefix<T>::value();
263			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
264			std::string FormatStr(detail::format("%smat2x3((%s, %s, %s), (%s, %s, %s))",
265				PrefixStr,
266				LiteralStr, LiteralStr, LiteralStr,
267				LiteralStr, LiteralStr, LiteralStr));
268
269			return detail::format(FormatStr.c_str(),
270				x[0][0], x[0][1], x[0][2],
271				x[1][0], x[1][1], x[1][2]);
272		}
273	};
274
275	template <typename T, precision P>
276	struct compute_to_string<tmat2x4, T, P>
277	{
278		GLM_FUNC_QUALIFIER static std::string call(tmat2x4<T, P> const & x)
279		{
280			char const * PrefixStr = prefix<T>::value();
281			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
282			std::string FormatStr(detail::format("%smat2x4((%s, %s, %s, %s), (%s, %s, %s, %s))",
283				PrefixStr,
284				LiteralStr, LiteralStr, LiteralStr, LiteralStr,
285				LiteralStr, LiteralStr, LiteralStr, LiteralStr));
286
287			return detail::format(FormatStr.c_str(),
288				x[0][0], x[0][1], x[0][2], x[0][3],
289				x[1][0], x[1][1], x[1][2], x[1][3]);
290		}
291	};
292
293	template <typename T, precision P>
294	struct compute_to_string<tmat3x2, T, P>
295	{
296		GLM_FUNC_QUALIFIER static std::string call(tmat3x2<T, P> const & x)
297		{
298			char const * PrefixStr = prefix<T>::value();
299			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
300			std::string FormatStr(detail::format("%smat3x2((%s, %s), (%s, %s), (%s, %s))",
301				PrefixStr,
302				LiteralStr, LiteralStr,
303				LiteralStr, LiteralStr,
304				LiteralStr, LiteralStr));
305
306			return detail::format(FormatStr.c_str(),
307				x[0][0], x[0][1],
308				x[1][0], x[1][1],
309				x[2][0], x[2][1]);
310		}
311	};
312
313	template <typename T, precision P>
314	struct compute_to_string<tmat3x3, T, P>
315	{
316		GLM_FUNC_QUALIFIER static std::string call(tmat3x3<T, P> const & x)
317		{
318			char const * PrefixStr = prefix<T>::value();
319			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
320			std::string FormatStr(detail::format("%smat3x3((%s, %s, %s), (%s, %s, %s), (%s, %s, %s))",
321				PrefixStr,
322				LiteralStr, LiteralStr, LiteralStr,
323				LiteralStr, LiteralStr, LiteralStr,
324				LiteralStr, LiteralStr, LiteralStr));
325
326			return detail::format(FormatStr.c_str(),
327				x[0][0], x[0][1], x[0][2],
328				x[1][0], x[1][1], x[1][2],
329				x[2][0], x[2][1], x[2][2]);
330		}
331	};
332
333	template <typename T, precision P>
334	struct compute_to_string<tmat3x4, T, P>
335	{
336		GLM_FUNC_QUALIFIER static std::string call(tmat3x4<T, P> const & x)
337		{
338			char const * PrefixStr = prefix<T>::value();
339			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
340			std::string FormatStr(detail::format("%smat3x4((%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s))",
341				PrefixStr,
342				LiteralStr, LiteralStr, LiteralStr, LiteralStr,
343				LiteralStr, LiteralStr, LiteralStr, LiteralStr,
344				LiteralStr, LiteralStr, LiteralStr, LiteralStr));
345
346			return detail::format(FormatStr.c_str(),
347				x[0][0], x[0][1], x[0][2], x[0][3],
348				x[1][0], x[1][1], x[1][2], x[1][3],
349				x[2][0], x[2][1], x[2][2], x[2][3]);
350		}
351	};
352
353	template <typename T, precision P>
354	struct compute_to_string<tmat4x2, T, P>
355	{
356		GLM_FUNC_QUALIFIER static std::string call(tmat4x2<T, P> const & x)
357		{
358			char const * PrefixStr = prefix<T>::value();
359			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
360			std::string FormatStr(detail::format("%smat4x2((%s, %s), (%s, %s), (%s, %s), (%s, %s))",
361				PrefixStr,
362				LiteralStr, LiteralStr,
363				LiteralStr, LiteralStr,
364				LiteralStr, LiteralStr,
365				LiteralStr, LiteralStr));
366
367			return detail::format(FormatStr.c_str(),
368				x[0][0], x[0][1],
369				x[1][0], x[1][1],
370				x[2][0], x[2][1],
371				x[3][0], x[3][1]);
372		}
373	};
374
375	template <typename T, precision P>
376	struct compute_to_string<tmat4x3, T, P>
377	{
378		GLM_FUNC_QUALIFIER static std::string call(tmat4x3<T, P> const & x)
379		{
380			char const * PrefixStr = prefix<T>::value();
381			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
382			std::string FormatStr(detail::format("%smat4x3((%s, %s, %s), (%s, %s, %s), (%s, %s, %s), (%s, %s, %s))",
383				PrefixStr,
384				LiteralStr, LiteralStr, LiteralStr,
385				LiteralStr, LiteralStr, LiteralStr,
386				LiteralStr, LiteralStr, LiteralStr,
387				LiteralStr, LiteralStr, LiteralStr));
388
389			return detail::format(FormatStr.c_str(),
390				x[0][0], x[0][1], x[0][2],
391				x[1][0], x[1][1], x[1][2],
392				x[2][0], x[2][1], x[2][2],
393				x[3][0], x[3][1], x[3][2]);
394		}
395	};
396
397	template <typename T, precision P>
398	struct compute_to_string<tmat4x4, T, P>
399	{
400		GLM_FUNC_QUALIFIER static std::string call(tmat4x4<T, P> const & x)
401		{
402			char const * PrefixStr = prefix<T>::value();
403			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
404			std::string FormatStr(detail::format("%smat4x4((%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s), (%s, %s, %s, %s))",
405				PrefixStr,
406				LiteralStr, LiteralStr, LiteralStr, LiteralStr,
407				LiteralStr, LiteralStr, LiteralStr, LiteralStr,
408				LiteralStr, LiteralStr, LiteralStr, LiteralStr,
409				LiteralStr, LiteralStr, LiteralStr, LiteralStr));
410
411			return detail::format(FormatStr.c_str(),
412				x[0][0], x[0][1], x[0][2], x[0][3],
413				x[1][0], x[1][1], x[1][2], x[1][3],
414				x[2][0], x[2][1], x[2][2], x[2][3],
415				x[3][0], x[3][1], x[3][2], x[3][3]);
416		}
417	};
418
419
420	template <typename T, precision P>
421	struct compute_to_string<tquat, T, P>
422	{
423		GLM_FUNC_QUALIFIER static std::string call(tquat<T, P> const & x)
424		{
425			char const * PrefixStr = prefix<T>::value();
426			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
427			std::string FormatStr(detail::format("%squat(%s, %s, %s, %s)",
428				PrefixStr,
429				LiteralStr, LiteralStr, LiteralStr, LiteralStr));
430
431			return detail::format(FormatStr.c_str(), x[0], x[1], x[2], x[3]);
432		}
433	};
434
435	template <typename T, precision P>
436	struct compute_to_string<tdualquat, T, P>
437	{
438		GLM_FUNC_QUALIFIER static std::string call(tdualquat<T, P> const & x)
439		{
440			char const * PrefixStr = prefix<T>::value();
441			char const * LiteralStr = literal<T, std::numeric_limits<T>::is_iec559>::value();
442			std::string FormatStr(detail::format("%sdualquat((%s, %s, %s, %s), (%s, %s, %s, %s))",
443				PrefixStr,
444				LiteralStr, LiteralStr, LiteralStr, LiteralStr));
445
446			return detail::format(FormatStr.c_str(), x.real[0], x.real[1], x.real[2], x.real[3], x.dual[0], x.dual[1], x.dual[2], x.dual[3]);
447		}
448	};
449
450}//namespace detail
451
452template <template <typename, precision> class matType, typename T, precision P>
453GLM_FUNC_QUALIFIER std::string to_string(matType<T, P> const & x)
454{
455	return detail::compute_to_string<matType, T, P>::call(x);
456}
457
458}//namespace glm
459