xref: /haiku/headers/private/kernel/util/KMessage.h (revision bea66afaeb8d038d8918106a430a56b6e9fb3109)
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 
18 class BMessage;
19 
20 
21 namespace BPrivate {
22 
23 class KMessageField;
24 class MessageAdapter;
25 
26 
27 class KMessage {
28 public:
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 
38 public:
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 
187 private:
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 
205 private:
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 
235 private:
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 
247 class KMessageField {
248 public:
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 
268 private:
269 			friend class KMessage;
270 
271 private:
272 			void				SetTo(KMessage* message, int32 headerOffset);
273 
274 			KMessage::FieldHeader* _Header() const;
275 
276 private:
277 			KMessage*			fMessage;
278 			int32				fHeaderOffset;
279 };
280 
281 } // namespace BPrivate
282 
283 
284 using BPrivate::KMessage;
285 using BPrivate::KMessageField;
286 
287 
288 // #pragma mark - inline functions
289 
290 
291 status_t
292 KMessage::AddBool(const char* name, bool value)
293 {
294 	return AddData(name, B_BOOL_TYPE, &value, sizeof(bool), true);
295 }
296 
297 
298 status_t
299 KMessage::AddInt8(const char* name, int8 value)
300 {
301 	return AddData(name, B_INT8_TYPE, &value, sizeof(int8), true);
302 }
303 
304 
305 status_t
306 KMessage::AddInt16(const char* name, int16 value)
307 {
308 	return AddData(name, B_INT16_TYPE, &value, sizeof(int16), true);
309 }
310 
311 
312 status_t
313 KMessage::AddInt32(const char* name, int32 value)
314 {
315 	return AddData(name, B_INT32_TYPE, &value, sizeof(int32), true);
316 }
317 
318 
319 status_t
320 KMessage::AddInt64(const char* name, int64 value)
321 {
322 	return AddData(name, B_INT64_TYPE, &value, sizeof(int64), true);
323 }
324 
325 
326 status_t
327 KMessage::AddPointer(const char* name, const void* value)
328 {
329 	return AddData(name, B_POINTER_TYPE, &value, sizeof(value), true);
330 }
331 
332 
333 // AddString
334 status_t
335 KMessage::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 
346 template<typename T>
347 status_t
348 KMessage::_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 
366 status_t
367 KMessage::FindBool(const char* name, bool* value) const
368 {
369 	return FindBool(name, 0, value);
370 }
371 
372 
373 status_t
374 KMessage::FindBool(const char* name, int32 index, bool* value) const
375 {
376 	return _FindType(name, B_BOOL_TYPE, index, value);
377 }
378 
379 
380 status_t
381 KMessage::FindInt8(const char* name, int8* value) const
382 {
383 	return FindInt8(name, 0, value);
384 }
385 
386 
387 status_t
388 KMessage::FindInt8(const char* name, int32 index, int8* value) const
389 {
390 	return _FindType(name, B_INT8_TYPE, index, value);
391 }
392 
393 
394 status_t
395 KMessage::FindInt16(const char* name, int16* value) const
396 {
397 	return FindInt16(name, 0, value);
398 }
399 
400 
401 status_t
402 KMessage::FindInt16(const char* name, int32 index, int16* value) const
403 {
404 	return _FindType(name, B_INT16_TYPE, index, value);
405 }
406 
407 
408 status_t
409 KMessage::FindInt32(const char* name, int32* value) const
410 {
411 	return FindInt32(name, 0, value);
412 }
413 
414 
415 status_t
416 KMessage::FindInt32(const char* name, int32 index, int32* value) const
417 {
418 	return _FindType(name, B_INT32_TYPE, index, value);
419 }
420 
421 
422 status_t
423 KMessage::FindInt64(const char* name, int64* value) const
424 {
425 	return FindInt64(name, 0, value);
426 }
427 
428 
429 status_t
430 KMessage::FindInt64(const char* name, int32 index, int64* value) const
431 {
432 	return _FindType(name, B_INT64_TYPE, index, value);
433 }
434 
435 
436 status_t
437 KMessage::FindPointer(const char* name, void** value) const
438 {
439 	return FindPointer(name, 0, value);
440 }
441 
442 
443 status_t
444 KMessage::FindPointer(const char* name, int32 index, void** value) const
445 {
446 	return _FindType(name, B_POINTER_TYPE, index, value);
447 }
448 
449 
450 status_t
451 KMessage::FindString(const char* name, const char** value) const
452 {
453 	return FindString(name, 0, value);
454 }
455 
456 
457 status_t
458 KMessage::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 
465 template<typename T>
466 inline T
467 KMessage::_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 
477 inline bool
478 KMessage::GetBool(const char* name, bool defaultValue) const
479 {
480 	return _GetType(name, B_BOOL_TYPE, 0, defaultValue);
481 }
482 
483 
484 inline bool
485 KMessage::GetBool(const char* name, int32 index, bool defaultValue) const
486 {
487 	return _GetType(name, B_BOOL_TYPE, index, defaultValue);
488 }
489 
490 
491 int8
492 KMessage::GetInt8(const char* name, int8 defaultValue) const
493 {
494 	return _GetType(name, B_INT8_TYPE, 0, defaultValue);
495 }
496 
497 
498 int8
499 KMessage::GetInt8(const char* name, int32 index, int8 defaultValue) const
500 {
501 	return _GetType(name, B_INT8_TYPE, index, defaultValue);
502 }
503 
504 
505 int16
506 KMessage::GetInt16(const char* name, int16 defaultValue) const
507 {
508 	return _GetType(name, B_INT16_TYPE, 0, defaultValue);
509 }
510 
511 
512 int16
513 KMessage::GetInt16(const char* name, int32 index, int16 defaultValue) const
514 {
515 	return _GetType(name, B_INT16_TYPE, index, defaultValue);
516 }
517 
518 
519 int32
520 KMessage::GetInt32(const char* name, int32 defaultValue) const
521 {
522 	return _GetType(name, B_INT32_TYPE, 0, defaultValue);
523 }
524 
525 
526 int32
527 KMessage::GetInt32(const char* name, int32 index, int32 defaultValue) const
528 {
529 	return _GetType(name, B_INT32_TYPE, index, defaultValue);
530 }
531 
532 
533 int64
534 KMessage::GetInt64(const char* name, int64 defaultValue) const
535 {
536 	return _GetType(name, B_INT64_TYPE, 0, defaultValue);
537 }
538 
539 
540 int64
541 KMessage::GetInt64(const char* name, int32 index, int64 defaultValue) const
542 {
543 	return _GetType(name, B_INT64_TYPE, index, defaultValue);
544 }
545 
546 
547 void*
548 KMessage::GetPointer(const char* name, const void* defaultValue) const
549 {
550 	return const_cast<void*>(_GetType(name, B_POINTER_TYPE, 0, defaultValue));
551 }
552 
553 
554 void*
555 KMessage::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 
563 const char*
564 KMessage::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 
578 const char*
579 KMessage::GetString(const char* name, const char* defaultValue) const
580 {
581 	return GetString(name, 0, defaultValue);
582 }
583 
584 
585 status_t
586 KMessage::SetBool(const char* name, bool value)
587 {
588 	return SetData(name, B_BOOL_TYPE, &value, sizeof(bool));
589 }
590 
591 
592 status_t
593 KMessage::SetInt8(const char* name, int8 value)
594 {
595 	return SetData(name, B_INT8_TYPE, &value, sizeof(int8));
596 }
597 
598 
599 status_t
600 KMessage::SetInt16(const char* name, int16 value)
601 {
602 	return SetData(name, B_INT16_TYPE, &value, sizeof(int16));
603 }
604 
605 
606 status_t
607 KMessage::SetInt32(const char* name, int32 value)
608 {
609 	return SetData(name, B_INT32_TYPE, &value, sizeof(int32));
610 }
611 
612 
613 status_t
614 KMessage::SetInt64(const char* name, int64 value)
615 {
616 	return SetData(name, B_INT64_TYPE, &value, sizeof(int64));
617 }
618 
619 
620 status_t
621 KMessage::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 
630 typedef 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