1/*
2 * Copyright 2005-2007, Haiku Inc. All rights reserved.
3 * Distributed under the terms of the MIT License.
4 *
5 * Authors:
6 * 		Ingo Weinhold <bonefish@cs.tu-berlin.de>
7 * 		Hugo Santos <hugosantos@gmail.com>
8 */
9
10#include "TypeHandler.h"
11
12#include <string.h>
13
14#include "Context.h"
15#include "MemoryReader.h"
16#include "Syscall.h"
17
18template<typename value_t>
19static inline value_t
20get_value(const void *address)
21{
22	if (sizeof(align_t) > sizeof(value_t))
23		return value_t(*(align_t*)address);
24	else
25		return *(value_t*)address;
26}
27
28// #pragma mark -
29
30// create_pointer_type_handler
31TypeHandler *
32create_pointer_type_handler()
33{
34	return new TypeHandlerImpl<const void*>();
35}
36
37// create_string_type_handler
38TypeHandler *
39create_string_type_handler()
40{
41	return new TypeHandlerImpl<const char*>();
42}
43
44// #pragma mark -
45
46// complete specializations
47
48// void
49template<>
50string
51TypeHandlerImpl<void>::GetParameterValue(Context &, Parameter *, const void *)
52{
53	return "void";
54}
55
56template<>
57string
58TypeHandlerImpl<void>::GetReturnValue(Context &, uint64 value)
59{
60	return "";
61}
62
63template<>
64TypeHandler *
65TypeHandlerFactory<void>::Create()
66{
67	return new TypeHandlerImpl<void>();
68}
69
70// bool
71template<>
72string
73TypeHandlerImpl<bool>::GetParameterValue(Context &, Parameter *,
74					 const void *address)
75{
76	return (*(const align_t*)address ? "true" : "false");
77}
78
79template<>
80string
81TypeHandlerImpl<bool>::GetReturnValue(Context &, uint64 value)
82{
83	return (value ? "true" : "false");
84}
85
86template<>
87TypeHandler *
88TypeHandlerFactory<bool>::Create()
89{
90	return new TypeHandlerImpl<bool>();
91}
92
93// read_string
94static
95string
96read_string(Context &context, void *data)
97{
98	if (data == NULL || !context.GetContents(Context::STRINGS))
99		return context.FormatPointer(data);
100
101	char buffer[256];
102	int32 bytesRead;
103	status_t error = context.Reader().Read(data, buffer, sizeof(buffer), bytesRead);
104	if (error == B_OK) {
105//		return string("\"") + string(buffer, bytesRead) + "\"";
106//string result("\"");
107//result += string(buffer, bytesRead);
108//result += "\"";
109//return result;
110
111// TODO: Unless I'm missing something obvious, our STL string class is broken.
112// The appended "\"" doesn't appear in either of the above cases.
113
114		int32 len = strnlen(buffer, sizeof(buffer));
115		char largeBuffer[259];
116		largeBuffer[0] = '"';
117		memcpy(largeBuffer + 1, buffer, len);
118		largeBuffer[len + 1] = '"';
119		largeBuffer[len + 2] = '\0';
120		return largeBuffer;
121	}
122
123	return context.FormatPointer(data) + " (" + strerror(error) + ")";
124}
125
126// const void*
127template<>
128string
129TypeHandlerImpl<const void*>::GetParameterValue(Context &context, Parameter *,
130						const void *address)
131{
132	return context.FormatPointer(*(void **)address);
133}
134
135template<>
136string
137TypeHandlerImpl<const void*>::GetReturnValue(Context &context, uint64 value)
138{
139	return context.FormatPointer((void *)value);
140}
141
142// const char*
143template<>
144string
145TypeHandlerImpl<const char*>::GetParameterValue(Context &context, Parameter *,
146						const void *address)
147{
148	return read_string(context, *(void **)address);
149}
150
151template<>
152string
153TypeHandlerImpl<const char*>::GetReturnValue(Context &context, uint64 value)
154{
155	return read_string(context, (void *)value);
156}
157
158EnumTypeHandler::EnumTypeHandler(const EnumMap &m) : fMap(m) {}
159
160string
161EnumTypeHandler::GetParameterValue(Context &context, Parameter *,
162				   const void *address)
163{
164	return RenderValue(context, get_value<unsigned int>(address));
165}
166
167string
168EnumTypeHandler::GetReturnValue(Context &context, uint64 value)
169{
170	return RenderValue(context, value);
171}
172
173string
174EnumTypeHandler::RenderValue(Context &context, unsigned int value) const
175{
176	if (context.GetContents(Context::ENUMERATIONS)) {
177		EnumMap::const_iterator i = fMap.find(value);
178		if (i != fMap.end() && i->second != NULL)
179			return i->second;
180	}
181
182	return context.FormatUnsigned(value);
183}
184
185TypeHandlerSelector::TypeHandlerSelector(const SelectMap &m, int sibling,
186					 TypeHandler *def)
187	: fMap(m), fSibling(sibling), fDefault(def) {}
188
189string
190TypeHandlerSelector::GetParameterValue(Context &context, Parameter *param,
191				       const void *address)
192{
193	TypeHandler *target = fDefault;
194
195	int index = get_value<int>(context.GetValue(context.GetSibling(fSibling)));
196
197	SelectMap::const_iterator i = fMap.find(index);
198	if (i != fMap.end())
199		target = i->second;
200
201	return target->GetParameterValue(context, param, address);
202}
203
204string
205TypeHandlerSelector::GetReturnValue(Context &context, uint64 value)
206{
207	return fDefault->GetReturnValue(context, value);
208}
209
210template<typename Type>
211static bool
212obtain_pointer_data(Context &context, Type *data, void *address, uint32 what)
213{
214	if (address == NULL || !context.GetContents(what))
215		return false;
216
217	int32 bytesRead;
218
219	status_t err = context.Reader().Read(address, data, sizeof(Type), bytesRead);
220	if (err != B_OK || bytesRead < (int32)sizeof(Type))
221		return false;
222
223	return true;
224}
225
226template<typename Type>
227static string
228format_signed_integer_pointer(Context &context, void *address)
229{
230	Type data;
231
232	if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES))
233		return "[" + context.FormatSigned(data, sizeof(Type)) + "]";
234
235	return context.FormatPointer(address);
236}
237
238template<typename Type>
239static string
240format_unsigned_integer_pointer(Context &context, void *address)
241{
242	Type data;
243
244	if (obtain_pointer_data(context, &data, address, Context::POINTER_VALUES))
245		return "[" + context.FormatUnsigned(data) + "]";
246
247	return context.FormatPointer(address);
248}
249
250template<typename Type>
251class SignedIntegerTypeHandler : public TypeHandler {
252public:
253	string GetParameterValue(Context &context, Parameter *,
254				 const void *address)
255	{
256		return context.FormatSigned(get_value<Type>(address), sizeof(Type));
257	}
258
259	string GetReturnValue(Context &context, uint64 value)
260	{
261		return context.FormatSigned(value, sizeof(Type));
262	}
263};
264
265template<typename Type>
266class UnsignedIntegerTypeHandler : public TypeHandler {
267public:
268	string GetParameterValue(Context &context, Parameter *,
269				 const void *address)
270	{
271		return context.FormatUnsigned(get_value<Type>(address));
272	}
273
274	string GetReturnValue(Context &context, uint64 value)
275	{
276		return context.FormatUnsigned(value);
277	}
278};
279
280template<typename Type>
281class SignedIntegerPointerTypeHandler : public TypeHandler {
282	string GetParameterValue(Context &context, Parameter *,
283				 const void *address)
284	{
285		return format_signed_integer_pointer<Type>(context, *(void **)address);
286	}
287
288	string GetReturnValue(Context &context, uint64 value)
289	{
290		return format_signed_integer_pointer<Type>(context, (void *)value);
291	}
292};
293
294template<typename Type>
295class UnsignedIntegerPointerTypeHandler : public TypeHandler {
296	string GetParameterValue(Context &context, Parameter *,
297				 const void *address)
298	{
299		return format_unsigned_integer_pointer<Type>(context, *(void **)address);
300	}
301
302	string GetReturnValue(Context &context, uint64 value)
303	{
304		return format_unsigned_integer_pointer<Type>(context, (void *)value);
305	}
306};
307
308#define SIGNED_INTEGER_TYPE(type) \
309	template<> \
310	TypeHandler * \
311	TypeHandlerFactory<type>::Create() \
312	{ \
313		return new SignedIntegerTypeHandler<type>(); \
314	}
315
316#define UNSIGNED_INTEGER_TYPE(type) \
317	template<> \
318	TypeHandler * \
319	TypeHandlerFactory<type>::Create() \
320	{ \
321		return new UnsignedIntegerTypeHandler<type>(); \
322	}
323
324#define SIGNED_INTEGER_POINTER_TYPE(name, type) \
325	TypeHandler *create_##name##_type_handler() \
326	{ \
327		return new SignedIntegerPointerTypeHandler<type>(); \
328	}
329
330#define UNSIGNED_INTEGER_POINTER_TYPE(name, type) \
331	TypeHandler *create_##name##_type_handler() \
332	{ \
333		return new UnsignedIntegerPointerTypeHandler<type>(); \
334	}
335
336
337SIGNED_INTEGER_TYPE(char);
338SIGNED_INTEGER_TYPE(short);
339SIGNED_INTEGER_TYPE(int);
340SIGNED_INTEGER_TYPE(long);
341SIGNED_INTEGER_TYPE(long long);
342
343UNSIGNED_INTEGER_TYPE(unsigned char);
344UNSIGNED_INTEGER_TYPE(unsigned short);
345UNSIGNED_INTEGER_TYPE(unsigned int);
346UNSIGNED_INTEGER_TYPE(unsigned long);
347UNSIGNED_INTEGER_TYPE(unsigned long long);
348
349SIGNED_INTEGER_POINTER_TYPE(int_ptr, int);
350SIGNED_INTEGER_POINTER_TYPE(long_ptr, long);
351SIGNED_INTEGER_POINTER_TYPE(longlong_ptr, long long);
352
353UNSIGNED_INTEGER_POINTER_TYPE(uint_ptr, unsigned int);
354UNSIGNED_INTEGER_POINTER_TYPE(ulong_ptr, unsigned long);
355UNSIGNED_INTEGER_POINTER_TYPE(ulonglong_ptr, unsigned long long);
356
357