1/*
2 * Copyright 2005-2009, Ingo Weinhold, ingo_weinhold@gmx.de.
3 * Distributed under the terms of the MIT License.
4 */
5#ifndef _KERNEL_UTIL_KMESSAGE_H
6#define _KERNEL_UTIL_KMESSAGE_H
7
8
9#include <string.h>
10
11#include <OS.h>
12#include <TypeConstants.h>
13
14
15#ifdef __cplusplus
16
17
18class BMessage;
19
20
21namespace BPrivate {
22
23class KMessageField;
24class MessageAdapter;
25
26
27class KMessage {
28public:
29			enum {
30				KMESSAGE_OWNS_BUFFER		= 0x01,
31				KMESSAGE_INIT_FROM_BUFFER	= 0x02,
32				KMESSAGE_CLONE_BUFFER		= 0x04,
33				KMESSAGE_READ_ONLY			= 0x08,
34
35				KMESSAGE_FLAG_MASK			= 0x07,
36			};
37
38public:
39								KMessage();
40								KMessage(uint32 what);
41								~KMessage();
42
43			status_t			SetTo(uint32 what, uint32 flags = 0);
44			status_t			SetTo(void* buffer, int32 bufferSize,
45									uint32 what, uint32 flags = 0);
46			status_t			SetTo(const void* buffer, int32 bufferSize = -1,
47									uint32 flags = 0);
48									// KMESSAGE_INIT_FROM_BUFFER and
49									// KMESSAGE_READ_ONLY are implied
50			void				Unset();
51
52			void				SetWhat(uint32 what);
53			uint32				What() const;
54
55			const void*			Buffer() const;
56			int32				BufferCapacity() const;
57			int32				ContentSize() const;
58
59			status_t			AddField(const char* name, type_code type,
60									int32 elementSize = -1,
61									KMessageField* field = NULL);
62			status_t			FindField(const char* name,
63									KMessageField* field) const;
64			status_t			FindField(const char* name, type_code type,
65									KMessageField* field) const;
66			status_t			GetNextField(KMessageField* field) const;
67			bool				IsEmpty() const;
68
69			status_t			AddData(const char* name, type_code type,
70									const void* data, int32 numBytes,
71									bool isFixedSize = true);
72			status_t			AddArray(const char* name, type_code type,
73									const void* data, int32 elementSize,
74									int32 elementCount);
75	inline	status_t			AddBool(const char* name, bool value);
76	inline	status_t			AddInt8(const char* name, int8 value);
77	inline	status_t			AddInt16(const char* name, int16 value);
78	inline	status_t			AddInt32(const char* name, int32 value);
79	inline	status_t			AddInt64(const char* name, int64 value);
80	inline	status_t			AddPointer(const char* name, const void* value);
81	inline	status_t			AddString(const char* name, const char* value);
82
83			status_t			FindData(const char* name, type_code type,
84									const void** data, int32* numBytes) const;
85			status_t			FindData(const char* name, type_code type,
86									int32 index, const void** data,
87									int32* numBytes) const;
88	inline	status_t			FindBool(const char* name, bool* value) const;
89	inline	status_t			FindBool(const char* name, int32 index,
90									bool* value) const;
91	inline	status_t			FindInt8(const char* name, int8* value) const;
92	inline	status_t			FindInt8(const char* name, int32 index,
93									int8* value) const;
94	inline	status_t			FindInt16(const char* name, int16* value) const;
95	inline	status_t			FindInt16(const char* name, int32 index,
96									int16* value) const;
97	inline	status_t			FindInt32(const char* name, int32* value) const;
98	inline	status_t			FindInt32(const char* name, int32 index,
99									int32* value) const;
100	inline	status_t			FindInt64(const char* name, int64* value) const;
101	inline	status_t			FindInt64(const char* name, int32 index,
102									int64* value) const;
103	inline	status_t			FindPointer(const char* name,
104									void** value) const;
105	inline	status_t			FindPointer(const char* name, int32 index,
106									void** value) const;
107	inline	status_t			FindString(const char* name,
108									const char** value) const;
109	inline	status_t			FindString(const char* name, int32 index,
110									const char** value) const;
111
112	inline	bool				GetBool(const char* name,
113									bool defaultValue) const;
114	inline	bool				GetBool(const char* name, int32 index,
115									bool defaultValue) const;
116	inline	int8				GetInt8(const char* name,
117									int8 defaultValue) const;
118	inline	int8				GetInt8(const char* name, int32 index,
119									int8 defaultValue) const;
120	inline	int16				GetInt16(const char* name,
121									int16 defaultValue) const;
122	inline	int16				GetInt16(const char* name, int32 index,
123									int16 defaultValue) const;
124	inline	int32				GetInt32(const char* name,
125									int32 defaultValue) const;
126	inline	int32				GetInt32(const char* name, int32 index,
127									int32 defaultValue) const;
128	inline	int64				GetInt64(const char* name,
129									int64 defaultValue) const;
130	inline	int64				GetInt64(const char* name, int32 index,
131									int64 defaultValue) const;
132	inline	void*				GetPointer(const char* name,
133									const void* defaultValue) const;
134	inline	void*				GetPointer(const char* name, int32 index,
135									const void* defaultValue) const;
136	inline	const char*			GetString(const char* name,
137									const char* defaultValue) const;
138	inline	const char*			GetString(const char* name, int32 index,
139									const char* defaultValue) const;
140
141	// fixed size fields only
142			status_t			SetData(const char* name, type_code type,
143									const void* data, int32 numBytes);
144	inline	status_t			SetBool(const char* name, bool value);
145	inline	status_t			SetInt8(const char* name, int8 value);
146	inline	status_t			SetInt16(const char* name, int16 value);
147	inline	status_t			SetInt32(const char* name, int32 value);
148	inline	status_t			SetInt64(const char* name, int64 value);
149	inline	status_t			SetPointer(const char* name, const void* value);
150
151	// message delivery
152			team_id				Sender() const;
153			int32				TargetToken() const;
154			port_id				ReplyPort() const;
155			int32				ReplyToken() const;
156
157			void				SetDeliveryInfo(int32 targetToken,
158									port_id replyPort, int32 replyToken,
159									team_id senderTeam);
160
161			status_t			SendTo(port_id targetPort,
162									int32 targetToken = -1,
163									port_id replyPort = -1,
164									int32 replyToken = -1,
165									bigtime_t timeout = -1,
166									team_id senderTeam = -1);
167			status_t			SendTo(port_id targetPort, int32 targetToken,
168									KMessage* reply,
169									bigtime_t deliveryTimeout = -1,
170									bigtime_t replyTimeout = -1,
171									team_id senderTeam = -1);
172			status_t			SendReply(KMessage* message,
173									port_id replyPort = -1,
174									int32 replyToken = -1,
175									bigtime_t timeout = -1,
176									team_id senderTeam = -1);
177			status_t			SendReply(KMessage* message, KMessage* reply,
178									bigtime_t deliveryTimeout = -1,
179									bigtime_t replyTimeout = -1,
180									team_id senderTeam = -1);
181			status_t			ReceiveFrom(port_id fromPort,
182									bigtime_t timeout = -1,
183									port_message_info* messageInfo = NULL);
184
185			void				Dump(void (*printFunc)(const char*, ...)) const;
186
187private:
188			friend class KMessageField;
189			friend class MessageAdapter;
190			friend class ::BMessage;	// not so nice, but makes things easier
191
192			struct Header {
193				uint32		magic;
194				int32		size;
195				uint32		what;
196				team_id		sender;
197				int32		targetToken;
198				port_id		replyPort;
199				int32		replyToken;
200			};
201
202			struct FieldHeader;
203			struct FieldValueHeader;
204
205private:
206			Header*				_Header() const;
207			int32				_BufferOffsetFor(const void* data) const;
208			FieldHeader*		_FirstFieldHeader() const;
209			FieldHeader*		_LastFieldHeader() const;
210			FieldHeader*		_FieldHeaderForOffset(int32 offset) const;
211			status_t			_AddField(const char* name, type_code type,
212									int32 elementSize, KMessageField* field);
213			status_t			_AddFieldData(KMessageField* field,
214									const void* data, int32 elementSize,
215									int32 elementCount);
216
217			status_t			_InitFromBuffer(bool sizeFromBuffer);
218			void				_InitBuffer(uint32 what);
219
220			void				_CheckBuffer();	// debugging only
221
222			status_t			_AllocateSpace(int32 size, bool alignAddress,
223									bool alignSize, void** address,
224									int32* alignedSize);
225			int32				_CapacityFor(int32 size);
226
227	template<typename T>
228	inline	status_t			_FindType(const char* name, type_code type,
229									int32 index, T* value) const;
230
231	template<typename T>
232	inline	T					_GetType(const char* name, type_code type,
233									int32 index, const T& defaultValue) const;
234
235private:
236			Header				fHeader;	// pointed to by fBuffer, if nothing
237											// is allocated
238			void*				fBuffer;
239			int32				fBufferCapacity;
240			uint32				fFlags;
241			int32				fLastFieldOffset;
242
243	static	const uint32		kMessageHeaderMagic;
244};
245
246
247class KMessageField {
248public:
249								KMessageField();
250
251			void				Unset();
252
253			KMessage*			Message() const;
254
255			const char*			Name() const;
256			type_code			TypeCode() const;
257			bool				HasFixedElementSize() const;
258			int32				ElementSize() const;
259									// only if HasFixedElementSize()
260
261			status_t			AddElement(const void* data, int32 size = -1);
262			status_t			AddElements(const void* data, int32 count,
263									int32 elementSize = -1);
264			const void*			ElementAt(int32 index,
265									int32* size = NULL) const;
266			int32				CountElements() const;
267
268private:
269			friend class KMessage;
270
271private:
272			void				SetTo(KMessage* message, int32 headerOffset);
273
274			KMessage::FieldHeader* _Header() const;
275
276private:
277			KMessage*			fMessage;
278			int32				fHeaderOffset;
279};
280
281} // namespace BPrivate
282
283
284using BPrivate::KMessage;
285using BPrivate::KMessageField;
286
287
288// #pragma mark - inline functions
289
290
291status_t
292KMessage::AddBool(const char* name, bool value)
293{
294	return AddData(name, B_BOOL_TYPE, &value, sizeof(bool), true);
295}
296
297
298status_t
299KMessage::AddInt8(const char* name, int8 value)
300{
301	return AddData(name, B_INT8_TYPE, &value, sizeof(int8), true);
302}
303
304
305status_t
306KMessage::AddInt16(const char* name, int16 value)
307{
308	return AddData(name, B_INT16_TYPE, &value, sizeof(int16), true);
309}
310
311
312status_t
313KMessage::AddInt32(const char* name, int32 value)
314{
315	return AddData(name, B_INT32_TYPE, &value, sizeof(int32), true);
316}
317
318
319status_t
320KMessage::AddInt64(const char* name, int64 value)
321{
322	return AddData(name, B_INT64_TYPE, &value, sizeof(int64), true);
323}
324
325
326status_t
327KMessage::AddPointer(const char* name, const void* value)
328{
329	return AddData(name, B_POINTER_TYPE, &value, sizeof(value), true);
330}
331
332
333// AddString
334status_t
335KMessage::AddString(const char* name, const char* value)
336{
337	if (!value)
338		return B_BAD_VALUE;
339	return AddData(name, B_STRING_TYPE, value, strlen(value) + 1, false);
340}
341
342
343// #pragma mark -
344
345
346template<typename T>
347status_t
348KMessage::_FindType(const char* name, type_code type, int32 index,
349	T* value) const
350{
351	const void* data;
352	int32 size;
353	status_t error = FindData(name, type, index, &data, &size);
354	if (error != B_OK)
355		return error;
356
357	if (size != sizeof(T))
358		return B_BAD_DATA;
359
360	*value = *(T*)data;
361
362	return B_OK;
363}
364
365
366status_t
367KMessage::FindBool(const char* name, bool* value) const
368{
369	return FindBool(name, 0, value);
370}
371
372
373status_t
374KMessage::FindBool(const char* name, int32 index, bool* value) const
375{
376	return _FindType(name, B_BOOL_TYPE, index, value);
377}
378
379
380status_t
381KMessage::FindInt8(const char* name, int8* value) const
382{
383	return FindInt8(name, 0, value);
384}
385
386
387status_t
388KMessage::FindInt8(const char* name, int32 index, int8* value) const
389{
390	return _FindType(name, B_INT8_TYPE, index, value);
391}
392
393
394status_t
395KMessage::FindInt16(const char* name, int16* value) const
396{
397	return FindInt16(name, 0, value);
398}
399
400
401status_t
402KMessage::FindInt16(const char* name, int32 index, int16* value) const
403{
404	return _FindType(name, B_INT16_TYPE, index, value);
405}
406
407
408status_t
409KMessage::FindInt32(const char* name, int32* value) const
410{
411	return FindInt32(name, 0, value);
412}
413
414
415status_t
416KMessage::FindInt32(const char* name, int32 index, int32* value) const
417{
418	return _FindType(name, B_INT32_TYPE, index, value);
419}
420
421
422status_t
423KMessage::FindInt64(const char* name, int64* value) const
424{
425	return FindInt64(name, 0, value);
426}
427
428
429status_t
430KMessage::FindInt64(const char* name, int32 index, int64* value) const
431{
432	return _FindType(name, B_INT64_TYPE, index, value);
433}
434
435
436status_t
437KMessage::FindPointer(const char* name, void** value) const
438{
439	return FindPointer(name, 0, value);
440}
441
442
443status_t
444KMessage::FindPointer(const char* name, int32 index, void** value) const
445{
446	return _FindType(name, B_POINTER_TYPE, index, value);
447}
448
449
450status_t
451KMessage::FindString(const char* name, const char** value) const
452{
453	return FindString(name, 0, value);
454}
455
456
457status_t
458KMessage::FindString(const char* name, int32 index, const char** value) const
459{
460	int32 size;
461	return FindData(name, B_STRING_TYPE, index, (const void**)value, &size);
462}
463
464
465template<typename T>
466inline T
467KMessage::_GetType(const char* name, type_code type, int32 index,
468	const T& defaultValue) const
469{
470	T value;
471	if (_FindType(name, type, index, &value) == B_OK)
472		return value;
473	return defaultValue;
474}
475
476
477inline bool
478KMessage::GetBool(const char* name, bool defaultValue) const
479{
480	return _GetType(name, B_BOOL_TYPE, 0, defaultValue);
481}
482
483
484inline bool
485KMessage::GetBool(const char* name, int32 index, bool defaultValue) const
486{
487	return _GetType(name, B_BOOL_TYPE, index, defaultValue);
488}
489
490
491int8
492KMessage::GetInt8(const char* name, int8 defaultValue) const
493{
494	return _GetType(name, B_INT8_TYPE, 0, defaultValue);
495}
496
497
498int8
499KMessage::GetInt8(const char* name, int32 index, int8 defaultValue) const
500{
501	return _GetType(name, B_INT8_TYPE, index, defaultValue);
502}
503
504
505int16
506KMessage::GetInt16(const char* name, int16 defaultValue) const
507{
508	return _GetType(name, B_INT16_TYPE, 0, defaultValue);
509}
510
511
512int16
513KMessage::GetInt16(const char* name, int32 index, int16 defaultValue) const
514{
515	return _GetType(name, B_INT16_TYPE, index, defaultValue);
516}
517
518
519int32
520KMessage::GetInt32(const char* name, int32 defaultValue) const
521{
522	return _GetType(name, B_INT32_TYPE, 0, defaultValue);
523}
524
525
526int32
527KMessage::GetInt32(const char* name, int32 index, int32 defaultValue) const
528{
529	return _GetType(name, B_INT32_TYPE, index, defaultValue);
530}
531
532
533int64
534KMessage::GetInt64(const char* name, int64 defaultValue) const
535{
536	return _GetType(name, B_INT64_TYPE, 0, defaultValue);
537}
538
539
540int64
541KMessage::GetInt64(const char* name, int32 index, int64 defaultValue) const
542{
543	return _GetType(name, B_INT64_TYPE, index, defaultValue);
544}
545
546
547void*
548KMessage::GetPointer(const char* name, const void* defaultValue) const
549{
550	return const_cast<void*>(_GetType(name, B_POINTER_TYPE, 0, defaultValue));
551}
552
553
554void*
555KMessage::GetPointer(const char* name, int32 index,
556	const void* defaultValue) const
557{
558	return const_cast<void*>(_GetType(name, B_POINTER_TYPE, index,
559		defaultValue));
560}
561
562
563const char*
564KMessage::GetString(const char* name, int32 index,
565	const char* defaultValue) const
566{
567	// don't use _GetType() here, since it checks field size == sizeof(T)
568	int32 size;
569	const char* value;
570	if (FindData(name, B_STRING_TYPE, index, (const void**)&value, &size)
571			== B_OK) {
572		return value;
573	}
574	return defaultValue;
575}
576
577
578const char*
579KMessage::GetString(const char* name, const char* defaultValue) const
580{
581	return GetString(name, 0, defaultValue);
582}
583
584
585status_t
586KMessage::SetBool(const char* name, bool value)
587{
588	return SetData(name, B_BOOL_TYPE, &value, sizeof(bool));
589}
590
591
592status_t
593KMessage::SetInt8(const char* name, int8 value)
594{
595	return SetData(name, B_INT8_TYPE, &value, sizeof(int8));
596}
597
598
599status_t
600KMessage::SetInt16(const char* name, int16 value)
601{
602	return SetData(name, B_INT16_TYPE, &value, sizeof(int16));
603}
604
605
606status_t
607KMessage::SetInt32(const char* name, int32 value)
608{
609	return SetData(name, B_INT32_TYPE, &value, sizeof(int32));
610}
611
612
613status_t
614KMessage::SetInt64(const char* name, int64 value)
615{
616	return SetData(name, B_INT64_TYPE, &value, sizeof(int64));
617}
618
619
620status_t
621KMessage::SetPointer(const char* name, const void* value)
622{
623	return SetData(name, B_POINTER_TYPE, &value, sizeof(value));
624}
625
626
627#else	// !__cplusplus
628
629
630typedef struct KMessage {
631	struct Header {
632		uint32		magic;
633		int32		size;
634		uint32		what;
635		team_id		sender;
636		int32		targetToken;
637		port_id		replyPort;
638		int32		replyToken;
639	}				fHeader;
640	void*			fBuffer;
641	int32			fBufferCapacity;
642	uint32			fFlags;
643	int32			fLastFieldOffset;
644} KMessage;
645
646
647#endif	// !__cplusplus
648
649
650#endif	// KMESSAGE_H
651